1303aad5fc8df025d0b20b84aac2a1496ddf47d5
[portal/sdk.git] /
1 /*
2  * ============LICENSE_START==========================================
3  * ONAP Portal SDK
4  * ===================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
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
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
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
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
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.
33  *
34  * ============LICENSE_END============================================
35  *
36  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
37  */
38 package org.onap.portalsdk.core.onboarding.crossapi;
39
40 import java.io.BufferedReader;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.InputStreamReader;
44 import java.io.PrintWriter;
45 import java.io.StringWriter;
46 import java.util.List;
47 import java.util.Map;
48
49 import javax.servlet.ServletException;
50 import javax.servlet.annotation.WebServlet;
51 import javax.servlet.http.HttpServlet;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.servlet.http.HttpServletResponse;
54
55 import org.apache.commons.logging.Log;
56 import org.apache.commons.logging.LogFactory;
57 import org.onap.portalsdk.core.onboarding.exception.PortalAPIException;
58 import org.onap.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
59 import org.onap.portalsdk.core.onboarding.rest.RestWebServiceClient;
60 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
61 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
62 import org.onap.portalsdk.core.restful.domain.EcompRole;
63 import org.onap.portalsdk.core.restful.domain.EcompUser;
64
65 import com.fasterxml.jackson.core.JsonProcessingException;
66 import com.fasterxml.jackson.core.type.TypeReference;
67 import com.fasterxml.jackson.databind.DeserializationFeature;
68 import com.fasterxml.jackson.databind.ObjectMapper;
69
70 /**
71  * This servlet performs the functions described below. It listens on a path
72  * like "/api" (see {@link PortalApiConstants#API_PREFIX}). The servlet checks
73  * for authorized access and rejects unauthorized requests.
74  * <OL>
75  * <LI>Proxies user (i.e., browser) requests for web analytics. The GET method
76  * fetches javascript from the Portal and returns it. The POST method forwards
77  * data sent by the browser on to Portal. These requests are checked for a valid
78  * User UID in a header; these requests do NOT use the application
79  * username-password header.</LI>
80  * <LI>Responds to ECOMP Portal API requests to query and update user, role and
81  * user-role information. The servlet proxies all requests on to a local Java
82  * class that implements {@link IPortalRestAPIService}. These requests must have
83  * the application username-password header.</LI>
84  * </OL>
85  * This servlet will not start if the required portal.properties file is not
86  * found on the classpath.
87  */
88
89 @WebServlet(urlPatterns = { PortalApiConstants.API_PREFIX + "/*" })
90 public class PortalRestAPIProxy extends HttpServlet implements IPortalRestAPIService {
91         
92         private static final long serialVersionUID = 1L;
93
94         private static final String APPLICATION_JSON = "application/json";
95
96         private static final Log logger = LogFactory.getLog(PortalRestAPIProxy.class);
97
98         /**
99          * Mapper for JSON to object etc.
100          */
101         private final ObjectMapper mapper = new ObjectMapper();
102
103         /**
104          * Client-supplied class that implements our interface.
105          */
106         private static IPortalRestAPIService portalRestApiServiceImpl;
107         private static final String isAccessCentralized = PortalApiProperties
108                         .getProperty(PortalApiConstants.ROLE_ACCESS_CENTRALIZED);
109         private static final String errorMessage = "Access Management is not allowed for Centralized applications." ;
110         private static final String isCentralized = "remote";
111
112
113         public PortalRestAPIProxy() {
114                 // Ensure that any additional fields sent by the Portal
115                 // will be ignored when creating objects.
116                 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
117         }
118
119         @Override
120         public void init() throws ServletException {
121                 String className = PortalApiProperties.getProperty(PortalApiConstants.PORTAL_API_IMPL_CLASS);
122                 if (className == null)
123                         throw new ServletException(
124                                         "init: Failed to find class name property " + PortalApiConstants.PORTAL_API_IMPL_CLASS);
125                 try {
126                         logger.debug("init: creating instance of class " + className);
127                         Class<?> implClass = Class.forName(className);
128                         portalRestApiServiceImpl = (IPortalRestAPIService) (implClass.getConstructor().newInstance());
129                 } catch (Exception ex) {
130                         throw new ServletException("init: Failed to find or instantiate class " + className, ex);
131                 }
132         }
133
134         @Override
135         protected void doPost(HttpServletRequest request, HttpServletResponse response)
136                         throws IOException, ServletException {
137                 if (portalRestApiServiceImpl == null) {
138                         // Should never happen due to checks in init()
139                         logger.error("doPost: no service class instance");
140                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
141                         response.getWriter().write(buildJsonResponse(false, "Misconfigured - no instance of service class"));
142                         return;
143                 }
144                 String requestUri = request.getRequestURI();
145                 String responseJson = "";
146                 String storeAnalyticsContextPath = "/storeAnalytics";
147                 if (requestUri.endsWith(PortalApiConstants.API_PREFIX + storeAnalyticsContextPath)) {
148                         String userId;
149                         try {
150                                 userId = getUserId(request);
151                         } catch (PortalAPIException e) {
152                                 logger.error("Issue with invoking getUserId implemenation !!! ", e);
153                                 throw new ServletException(e);
154                         }
155                         if (userId == null || userId.length() == 0) {
156                                 logger.debug("doPost: userId is null or empty");
157                                 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
158                                 responseJson = buildJsonResponse(false, "Not authorized for " + storeAnalyticsContextPath);
159                         } else {
160                                 // User ID obtained from request
161                                 try {
162                                         String credential = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
163                                         // for now lets also pass uebkey as user name and password
164                                         String requestBody = readRequestBody(request);
165                                         @SuppressWarnings("unchecked")
166                                         Map<String, String> bodyMap = mapper.readValue(requestBody, Map.class);
167                                         // add user ID
168                                         bodyMap.put("userid", userId);
169                                         requestBody = mapper.writeValueAsString(bodyMap);
170                                         responseJson = RestWebServiceClient.getInstance().postPortalContent(storeAnalyticsContextPath,
171                                                         userId, credential, null, credential, credential, "application/json", requestBody, true);
172                                         logger.debug("doPost: postPortalContent returns " + responseJson);
173                                         response.setStatus(HttpServletResponse.SC_OK);
174                                 } catch (Exception ex) {
175                                         logger.error("doPost: " + storeAnalyticsContextPath + " caught exception", ex);
176                                         responseJson = buildJsonResponse(ex);
177                                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
178                                 }
179                         }
180                         writeAndFlush(response, APPLICATION_JSON, responseJson);
181                         return;
182                 } // post analytics
183
184                 boolean secure = false;
185                 try {
186                         secure = isAppAuthenticated(request);
187                 } catch (PortalAPIException ex) {
188                         logger.error("doPost: isAppAuthenticated threw exception", ex);
189                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
190                         response.getWriter().write(buildJsonResponse(false, "Failed to authenticate request"));
191                         return;
192                 }
193                 if (!secure) {
194                         logger.debug("doPost: isAppAuthenticated answered false");
195                         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
196                         writeAndFlush(response, APPLICATION_JSON, buildJsonResponse(false, "Not authorized"));
197                         return;
198                 }
199
200                 try {
201                         String requestBody = readRequestBody(request);
202                         if (logger.isDebugEnabled())
203                                 logger.debug("doPost: URI =  " + requestUri + ", payload = " + requestBody);
204
205                         /*
206                          * All APIs:
207                          * 
208                          * 1. /user <-- save user
209                          * 
210                          * 2. /user/{loginId} <-- edit user
211                          * 
212                          * 3. /user/{loginId}/roles <-- save roles for user
213                          */
214
215                         // On success return the empty string.
216
217                         if (requestUri.endsWith("/updateSessionTimeOuts")) {
218                                 if (updateSessionTimeOuts(requestBody)) {
219                                         logger.debug("doPost: updated session timeouts");
220                                         response.setStatus(HttpServletResponse.SC_OK);
221                                 } else {
222                                         String msg = "Failed to update session time outs";
223                                         logger.error("doPost: " + msg);
224                                         responseJson = buildJsonResponse(false, msg);
225                                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
226                                 }
227                         } else if (requestUri.endsWith("/timeoutSession")) {
228                                 String portalJSessionId = request.getParameter("portalJSessionId");
229                                 if (portalJSessionId == null) {
230                                         portalJSessionId = "";
231                                 }
232                                 if (timeoutSession(portalJSessionId)) {
233                                         logger.debug("doPost: timed out session");
234                                         response.setStatus(HttpServletResponse.SC_OK);
235                                 } else {
236                                         String msg = "Failed to timeout session";
237                                         logger.error("doPost: " + msg);
238                                         responseJson = buildJsonResponse(false, msg);
239                                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
240                                 }
241                         } else
242                         // Example: /user <-- create user
243                         if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/user")) {
244                                 try {
245                                         if (isCentralized.equals(isAccessCentralized)) {
246                                                 responseJson = buildJsonResponse(true, errorMessage);
247                                                 response.setStatus(HttpServletResponse.SC_OK);
248                                         } else {
249                                                 EcompUser user = mapper.readValue(requestBody, EcompUser.class);
250                                                 pushUser(user);
251                                                 if (logger.isDebugEnabled())
252                                                         logger.debug("doPost: pushUser: success");
253                                                 responseJson = buildJsonResponse(true, null);
254                                                 response.setStatus(HttpServletResponse.SC_OK);
255                                         }
256                                 } catch (Exception ex) {
257                                         responseJson = buildJsonResponse(ex);
258                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
259                                         logger.error("doPost: pushUser: caught exception", ex);
260                                 }
261                         } else
262                         // Example: /user/abc <-- edit user abc 
263                         if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !(requestUri.endsWith("/roles"))) {
264                                 String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
265                                 try {
266                                         if (isCentralized.equals(isAccessCentralized)) {
267                                                 responseJson = buildJsonResponse(true, errorMessage);
268                                                 response.setStatus(HttpServletResponse.SC_OK);
269                                         } else {
270                                                 EcompUser user = mapper.readValue(requestBody, EcompUser.class);
271                                                 editUser(loginId, user);
272                                                 if (logger.isDebugEnabled())
273                                                         logger.debug("doPost: editUser: success");
274                                                 responseJson = buildJsonResponse(true, null);
275                                                 response.setStatus(HttpServletResponse.SC_OK);
276                                         }
277                                 } catch (Exception ex) {
278                                         responseJson = buildJsonResponse(ex);
279                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
280                                         logger.error("doPost: editUser: caught exception", ex);
281                                 }
282                         } else
283                         // Example: /user/{loginId}/roles <-- save roles for user
284                         if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
285                                 String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
286                                                 requestUri.lastIndexOf('/'));
287                                 try {
288                                         if (isCentralized.equals(isAccessCentralized)) {
289                                                 responseJson = buildJsonResponse(true, errorMessage);
290                                                 response.setStatus(HttpServletResponse.SC_OK);
291                                         } else {
292                                                 TypeReference<List<EcompRole>> typeRef = new TypeReference<List<EcompRole>>() {
293                                                 };
294                                                 List<EcompRole> roles = mapper.readValue(requestBody, typeRef);
295                                                 pushUserRole(loginId, roles);
296                                                 if (logger.isDebugEnabled())
297                                                         logger.debug("doPost: pushUserRole: success");
298                                                 responseJson = buildJsonResponse(true, null);
299                                                 response.setStatus(HttpServletResponse.SC_OK);
300                                         }
301                                 } catch (Exception ex) {
302                                         responseJson = buildJsonResponse(ex);
303                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
304                                         logger.error("doPost: pushUserRole: caught exception", ex);
305                                 }
306                         } else {
307                                 String msg = "doPost: no match for request " + requestUri;
308                                 logger.warn(msg);
309                                 responseJson = buildJsonResponse(false, msg);
310                                 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
311                         }
312                 } catch (Exception ex) {
313                         logger.error("doPost: Failed to process request " + requestUri, ex);
314                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
315                         responseJson = buildJsonResponse(ex);
316                 }
317
318                 writeAndFlush(response, APPLICATION_JSON, responseJson);
319
320         }
321
322         @Override
323         protected void doGet(HttpServletRequest request, HttpServletResponse response)
324                         throws IOException, ServletException {
325
326                 if (portalRestApiServiceImpl == null) {
327                         // Should never happen due to checks in init()
328                         logger.error("doGet: no service class instance");
329                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
330                         writeAndFlush(response, APPLICATION_JSON,
331                                         buildJsonResponse(false, "Misconfigured - no instance of service class"));
332                         return;
333                 }
334
335                 String requestUri = request.getRequestURI();
336                 String contentType = APPLICATION_JSON;
337                 String webAnalyticsContextPath = "/analytics";
338                 if (requestUri.endsWith(PortalApiConstants.API_PREFIX + webAnalyticsContextPath)) {
339                         String responseString;
340                         String userId;
341                         try {
342                                 userId = getUserId(request);
343                         } catch (PortalAPIException e) {
344                                 logger.error("Issue with invoking getUserId implemenation !!! ", e);
345                                 throw new ServletException(e);
346                         }
347                         if (userId == null || userId.length() == 0) {
348                                 logger.debug("doGet: userId is null or empty");
349                                 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
350                                 responseString = buildJsonResponse(false, "Not authorized for " + webAnalyticsContextPath);
351                         } else {
352                                 // User ID obtained from request
353                                 try {
354                                         String credential = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
355                                         // for now lets also pass uebkey as user name and password
356                                         contentType = "text/javascript";
357
358                                         responseString = RestWebServiceClient.getInstance().getPortalContent(webAnalyticsContextPath,
359                                                         userId, credential, null, credential, credential, true);
360                                         if (logger.isDebugEnabled())
361                                                 logger.debug("doGet: " + webAnalyticsContextPath + ": " + responseString);
362                                         response.setStatus(HttpServletResponse.SC_OK);
363                                 } catch (Exception ex) {
364                                         responseString = buildJsonResponse(ex);
365                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
366                                         logger.error("doGet: " + webAnalyticsContextPath + " caught exception", ex);
367                                 }
368                         }
369                         writeAndFlush(response, contentType, responseString);
370                         return;
371                 }
372
373                 boolean secure = false;
374                 try {
375                         secure = isAppAuthenticated(request);
376                 } catch (PortalAPIException ex) {
377                         logger.error("doGet: isAppAuthenticated threw exception", ex);
378                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
379                         writeAndFlush(response, APPLICATION_JSON, buildJsonResponse(false, "Failed to authenticate request"));
380                         return;
381                 }
382
383                 if (!secure) {
384                         if (logger.isDebugEnabled())
385                                 logger.debug("doGet: isAppAuthenticated answered false");
386                         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
387                         writeAndFlush(response, APPLICATION_JSON, buildJsonResponse(false, "Not authorized"));
388                         return;
389                 }
390
391                 String responseJson = null;
392                 try {
393                         // Ignore any request body in a GET.
394                         logger.debug("doGet: URI =  " + requestUri);
395
396                         /*
397                          * 1. /roles <-- get roles
398                          * 
399                          * 2. /user/{loginId} <-- get user
400                          * 
401                          * 3. /users <-- get all users
402                          * 
403                          * 4. /user/{loginId}/roles <-- get roles for user
404                          */
405
406                         if (requestUri.endsWith("/sessionTimeOuts")) {
407                                 try  {
408                                         responseJson = getSessionTimeOuts();
409                                         logger.debug("doGet: got session timeouts");
410                                         response.setStatus(HttpServletResponse.SC_OK);
411                                 } catch(Exception ex) {
412                                         String msg = "Failed to get session time outs";
413                                         logger.error("doGet: " + msg);
414                                         responseJson = buildJsonResponse(false, msg);
415                                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
416                                 }
417                         } else
418                         // Example: /users <-- get all users
419                         if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/users")) {
420                                 try {
421                                         List<EcompUser> users = getUsers();
422                                         responseJson = mapper.writeValueAsString(users);
423                                         if (logger.isDebugEnabled())
424                                                 logger.debug("doGet: getUsers: " + responseJson);
425                                 } catch (Exception ex) {
426                                         responseJson = buildShortJsonResponse(ex);
427                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
428                                         logger.error("doGet: getUsers: caught exception", ex);
429                                 }
430                         } else
431                         // Example: /roles <-- get all roles
432
433                         if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/roles")) {
434                                 try {
435                                         List<EcompRole> roles = getAvailableRoles(getUserId(request));
436                                         responseJson = mapper.writeValueAsString(roles);
437                                         if (logger.isDebugEnabled())
438                                                 logger.debug("doGet: getAvailableRoles: " + responseJson);
439                                 } catch (Exception ex) {
440                                         responseJson = buildJsonResponse(ex);
441                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
442                                         logger.error("doGet: getAvailableRoles: caught exception", ex);
443                                 }
444                         } else
445                         // Example: /user/abc <-- get user abc
446                         if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !requestUri.endsWith("/roles")) {
447                                 String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
448                                 try {
449                                         EcompUser user = getUser(loginId);
450                                         responseJson = mapper.writeValueAsString(user);
451                                         if (logger.isDebugEnabled())
452                                                 logger.debug("doGet: getUser: " + responseJson);
453                                 } catch (Exception ex) {
454                                         responseJson = buildJsonResponse(ex);
455                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
456                                         logger.error("doGet: getUser: caught exception", ex);
457                                 }
458                         }
459                         // Example: /user/abc/roles <-- get roles for user abc
460                         else if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
461                                 String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
462                                                 requestUri.lastIndexOf('/'));
463                                 try {
464                                         List<EcompRole> roles = getUserRoles(loginId);
465                                         responseJson = mapper.writeValueAsString(roles);
466                                         if (logger.isDebugEnabled())
467                                                 logger.debug("doGet: getUserRoles: " + responseJson);
468                                 } catch (Exception ex) {
469                                         responseJson = buildJsonResponse(ex);
470                                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
471                                         logger.error("doGet: getUserRoles: caught exception", ex);
472                                 }
473                         } else {
474                                 logger.warn("doGet: no match found for request");
475                                 responseJson = buildJsonResponse(false, "No match for request");
476                                 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
477                         }
478                 } catch (Exception ex) {
479                         logger.error("doGet: Failed to process request", ex);
480                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
481                         responseJson = buildJsonResponse(ex);
482                 }
483                 writeAndFlush(response, APPLICATION_JSON, responseJson);
484         }
485
486         public String getSessionTimeOuts() {
487                 return PortalTimeoutHandler.gatherSessionExtensions();
488         }
489
490         public boolean timeoutSession(String portalJSessionId) {
491                 return PortalTimeoutHandler.invalidateSession(portalJSessionId);
492         }
493
494         public boolean updateSessionTimeOuts(String sessionMap) {
495                 return PortalTimeoutHandler.updateSessionExtensions(sessionMap);
496         }
497
498         @Override
499         public void pushUser(EcompUser user) throws PortalAPIException {
500                 portalRestApiServiceImpl.pushUser(user);
501         }
502
503         @Override
504         public void editUser(String loginId, EcompUser user) throws PortalAPIException {
505                 portalRestApiServiceImpl.editUser(loginId, user);
506         }
507
508         @Override
509         public EcompUser getUser(String loginId) throws PortalAPIException {
510                 return portalRestApiServiceImpl.getUser(loginId);
511         }
512
513         @Override
514         public List<EcompUser> getUsers() throws PortalAPIException {
515                 return portalRestApiServiceImpl.getUsers();
516         }
517
518         @Override
519         public List<EcompRole> getAvailableRoles(String requestedLoginId) throws PortalAPIException {
520                 return portalRestApiServiceImpl.getAvailableRoles(requestedLoginId);
521         }
522
523         @Override
524         public void pushUserRole(String loginId, List<EcompRole> roles) throws PortalAPIException {
525                 portalRestApiServiceImpl.pushUserRole(loginId, roles);
526         }
527
528         @Override
529         public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException {
530                 return portalRestApiServiceImpl.getUserRoles(loginId);
531         }
532
533         @Override
534         public boolean isAppAuthenticated(HttpServletRequest request) throws PortalAPIException {
535                 return portalRestApiServiceImpl.isAppAuthenticated(request);
536         }
537
538         /**
539          * Sets the content type and writes the response.
540          * 
541          * @param response
542          * @param contentType
543          * @param responseBody
544          * @throws IOException
545          */
546         private void writeAndFlush(HttpServletResponse response, String contentType, String responseBody)
547                         throws IOException {
548                 response.setContentType(contentType);
549                 PrintWriter out = response.getWriter();
550                 out.print(responseBody);
551                 out.flush();
552         }
553
554         /**
555          * Reads the request body and closes the input stream.
556          * 
557          * @param request
558          * @return String read from the request, the empty string if nothing is read.
559          * @throws IOException
560          */
561         private static String readRequestBody(HttpServletRequest request) throws IOException {
562
563                 String body = null;
564                 StringBuilder stringBuilder = new StringBuilder();
565                 BufferedReader bufferedReader = null;
566                 try {
567                         InputStream inputStream = request.getInputStream();
568                         if (inputStream != null) {
569                                 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
570                                 char[] charBuffer = new char[1024];
571                                 int bytesRead = -1;
572                                 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
573                                         stringBuilder.append(charBuffer, 0, bytesRead);
574                                 }
575                         } else {
576                                 stringBuilder.append("");
577                         }
578                 } finally {
579                         if (bufferedReader != null) {
580                                 try {
581                                         bufferedReader.close();
582                                 } catch (IOException ex) {
583                                         logger.error("readRequestBody", ex);
584                                 }
585                         }
586                 }
587                 body = stringBuilder.toString();
588                 return body;
589         }
590
591         /**
592          * Builds JSON object with status + message response body.
593          * 
594          * @param success
595          *            True to indicate success, false to signal failure.
596          * @param msg
597          *            Message to include in the response object; ignored if null.
598          * @return
599          * 
600          *         <pre>
601          * { "status" : "ok" (or "error"), "message": "some explanation" }
602          *         </pre>
603          */
604         private String buildJsonResponse(boolean success, String msg) {
605                 PortalAPIResponse response = new PortalAPIResponse(success, msg);
606                 String json = null;
607                 try {
608                         json = mapper.writeValueAsString(response);
609                 } catch (JsonProcessingException ex) {
610                         // Truly should never, ever happen
611                         logger.error("buildJsonResponse", ex);
612                         json = "{ \"status\": \"error\",\"message\":\"" + ex.toString() + "\" }";
613                 }
614                 return json;
615         }
616
617         /**
618          * Builds JSON object with status of error and message containing stack trace
619          * for the specified throwable.
620          * 
621          * @param t
622          *            Throwable with stack trace to use as message
623          * 
624          * @return
625          * 
626          *         <pre>
627          * { "status" : "error", "message": "some-big-stacktrace" }
628          *         </pre>
629          */
630         private String buildJsonResponse(Throwable t) {
631                 StringWriter sw = new StringWriter();
632                 PrintWriter pw = new PrintWriter(sw);
633                 t.printStackTrace(pw);
634                 return buildJsonResponse(false, sw.toString());
635         }
636         
637         private String buildShortJsonResponse(Throwable t)
638         {
639                 String errorMessage = t.getMessage();
640                 return buildJsonResponse(false, errorMessage);
641         }
642
643         @Override
644         public String getUserId(HttpServletRequest request) throws PortalAPIException {
645                 return portalRestApiServiceImpl.getUserId(request);
646         }
647
648         public static IPortalRestAPIService getPortalRestApiServiceImpl() {
649                 return portalRestApiServiceImpl;
650         }
651
652         public static void setPortalRestApiServiceImpl(IPortalRestAPIService portalRestApiServiceImpl) {
653                 PortalRestAPIProxy.portalRestApiServiceImpl = portalRestApiServiceImpl;
654         }
655
656 }