1b3c79c0aa14bf6e82075805720e79324550d04d
[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  * 
37  */
38 package org.onap.portalsdk.core.onboarding.listener;
39
40 import java.util.Calendar;
41 import java.util.Hashtable;
42 import java.util.Map;
43
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpSession;
46
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49 import org.onap.portalsdk.core.onboarding.crossapi.SessionCommunicationService;
50 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
51 import org.onap.portalsdk.core.restful.domain.PortalTimeoutVO;
52
53 import com.fasterxml.jackson.core.JsonProcessingException;
54 import com.fasterxml.jackson.core.type.TypeReference;
55 import com.fasterxml.jackson.databind.ObjectMapper;
56
57 /**
58  * Invoked by listeners (UserContextListener and UserSessionListener) to track
59  * user sessions.
60  */
61 public class PortalTimeoutHandler {
62
63         private static final Map<String, HttpSession> sessionMap = new Hashtable<String, HttpSession>();
64         private static final Log logger = LogFactory.getLog(PortalTimeoutHandler.class);
65         private static ObjectMapper mapper = new ObjectMapper();
66         private static PortalTimeoutHandler timeoutHandler;
67
68         protected static final SessionCommInf sessionComm = new SessionComm();
69
70         public interface SessionCommInf {
71                 public Integer fetchSessionSlotCheckInterval(String... params);
72
73                 public void extendSessionTimeOuts(String... sessionMap);
74         }
75
76         public static class SessionComm implements SessionCommInf {
77                 
78                 @Override
79                 public Integer fetchSessionSlotCheckInterval(String... params) {
80                         String ecompRestURL = params[0];
81                         String userName = params[1];
82                         String pwd = params[2];
83                         String uebKey = params[3];
84                         String sessionSlot = SessionCommunicationService.getSessionSlotCheckInterval(ecompRestURL, userName, pwd,
85                                         uebKey);
86                         if (sessionSlot == null)
87                                 return null;
88                         return Integer.parseInt(sessionSlot);
89                 }
90
91                 @Override
92                 public void extendSessionTimeOuts(String... params) {
93                         String ecompRestURL = params[0];
94                         String userName = params[1];
95                         String pwd = params[2];
96                         String uebKey = params[3];
97                         String sessionTimeoutMap = params[4];
98                         SessionCommunicationService.requestPortalSessionTimeoutExtension(ecompRestURL, userName, pwd, uebKey,
99                                         sessionTimeoutMap);
100                 }
101         }
102
103         public static Map<String, HttpSession> getSessionMap() {
104                 return sessionMap;
105         }
106         
107         public static PortalTimeoutHandler getInstance() {
108                 if (timeoutHandler == null)
109                         timeoutHandler = new PortalTimeoutHandler();
110
111                 return timeoutHandler;
112         }
113
114         /**
115          * TODO: remove static
116          * 
117          * @param portalJSessionId
118          *            Portal (remote) session ID
119          * @param jSessionId
120          *            Local session ID
121          * @param session
122          *            HttpSession
123          */
124         public static void sessionCreated(String portalJSessionId, String jSessionId, HttpSession session) {
125
126                 storeMaxInactiveTime(session);
127
128                 // this key is a combination of portal jsession id and app session id
129                 String jSessionKey = jSessionKey(jSessionId, portalJSessionId);
130                 Object jSessionKeySessionVal = session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID);
131
132                 // do not reset the attributes if the same values have already been set
133                 // because that will cause PortalTimeoutBindingListener to unbound the
134                 // value from map
135                 if (jSessionKeySessionVal != null && jSessionKeySessionVal.equals(jSessionKey)) {
136                         logger.debug(" Session Values already exist in te map for sessionKey " + jSessionKey);
137                         return;
138                 }
139
140                 session.setAttribute(PortalApiConstants.PORTAL_JSESSION_ID, jSessionKey);
141
142                 // session binding listener will add this value to the static map
143                 // and with session replication the listener will fire in all tomcat
144                 // instances
145                 session.setAttribute(PortalApiConstants.PORTAL_JSESSION_BIND, new PortalTimeoutBindingListener());
146         }
147
148         /**
149          * TODO: remove static
150          * 
151          * @param session
152          */
153         protected static void storeMaxInactiveTime(HttpSession session) {
154                 if (session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME) == null)
155                         session.setAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME, session.getMaxInactiveInterval());
156         }
157
158         /**
159          * TODO: remove static
160          * 
161          * @param session
162          *            HttpSession
163          */
164         public static void sessionDestroyed(HttpSession session) {
165                 try {
166                         logger.info(" Session getting destroyed - id: " + session.getId());
167                         session.removeAttribute(PortalApiConstants.PORTAL_JSESSION_BIND);
168                 } catch (Exception e) {
169                         logger.error("sessionDestroyed failed", e);
170                 }
171         }
172
173         /***
174          * TODO: remove static
175          * 
176          * @param portalJSessionId
177          *            Portal session ID
178          * @return true on success, false if the session cannot be found, etc.
179          */
180         public static boolean invalidateSession(String portalJSessionId) {
181                 boolean result = false;
182                 logger.debug("Session Management: request from Portal to invalidate the session: " + portalJSessionId);
183                 for (String jSessionKey : sessionMap.keySet()) {
184                         try {
185                                 HttpSession session = sessionMap.get(jSessionKey);
186                                 if (portalJSessionId(jSessionKey).equals(portalJSessionId)) {
187                                         session.invalidate();
188                                         result = true;
189                                 }
190                         } catch (Exception e) {
191                                 logger.error("invalidateSession failed", e);
192                         }
193                 }
194                 return result;
195         }
196
197         /**
198          * TODO: remove static
199          * 
200          * @return json version of the timeout map: session ID -> timeout object
201          */
202         public static String gatherSessionExtensions() {
203                 logger.debug("Session Management: gatherSessionExtensions");
204
205                 Map<String, PortalTimeoutVO> sessionTimeoutMap = new Hashtable<>();
206                 String jsonMap = "";
207
208                 for (String jSessionKey : sessionMap.keySet()) {
209
210                         try {
211                                 // get the expiry time in seconds
212                                 HttpSession session = sessionMap.get(jSessionKey);
213
214                                 Long lastAccessedTimeMilliSec = session.getLastAccessedTime();
215                                 Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L;
216                                 Calendar instance = Calendar.getInstance();
217                                 instance.setTimeInMillis(session.getLastAccessedTime());
218                                 logger.debug("Session Management: Last Accessed time for " + jSessionKey + ": " + instance.getTime());
219
220                                 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
221
222                                 sessionTimeoutMap.put(portalJSessionId(jSessionKey),
223                                                 getSingleSessionTimeoutObj(jSessionKey, sessionTimOutMilliSec));
224                                 logger.debug("Session Management: putting session in map " + jSessionKey + " sessionTimoutSec"
225                                                 + (int) (sessionTimOutMilliSec / 1000));
226
227                                 jsonMap = mapper.writeValueAsString(sessionTimeoutMap);
228
229                         } catch (Exception e) {
230                                 logger.error("gatherSessionExtensions failed", e);
231                         }
232
233                 }
234                 return jsonMap;
235         }
236
237         /**
238          * TODO: remove static
239          * 
240          * @param sessionTimeoutMapStr
241          * Session timeout map as string
242          * @return true on success, false otherwise
243          */
244         public static boolean updateSessionExtensions(String sessionTimeoutMapStr) {
245                 logger.debug("Session Management: updateSessionExtensions");
246                 Map<String, PortalTimeoutVO> sessionTimeoutMap = null;
247                 try {
248                         TypeReference<Hashtable<String, PortalTimeoutVO>> typeRef = new TypeReference<Hashtable<String, PortalTimeoutVO>>() {
249                         };
250                         sessionTimeoutMap = mapper.readValue(sessionTimeoutMapStr, typeRef);
251                 } catch (Exception e) {
252                         logger.error("updateSessionExtensions failed to parse the sessionTimeoutMap from portal", e);
253                         return false;
254                 }
255
256                 boolean result = true;
257                 for (String jPortalSessionId : sessionTimeoutMap.keySet()) {
258                         try {
259                                 PortalTimeoutVO extendedTimeoutVO = mapper.readValue(
260                                                 mapper.writeValueAsString(sessionTimeoutMap.get(jPortalSessionId)), PortalTimeoutVO.class);
261                                 HttpSession session = sessionMap.get(jSessionKey(extendedTimeoutVO.getjSessionId(), jPortalSessionId));
262
263                                 if (session == null) {
264                                         continue;
265                                 }
266
267                                 Long lastAccessedTimeMilliSec = session.getLastAccessedTime();
268                                 Long maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000L;
269                                 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
270
271                                 Long maxTimeoutTimeMilliSec = extendedTimeoutVO.getSessionTimOutMilliSec();
272                                 if (maxTimeoutTimeMilliSec > sessionTimOutMilliSec) {
273                                         session.setMaxInactiveInterval((int) (maxTimeoutTimeMilliSec - lastAccessedTimeMilliSec) / 1000);
274                                         logger.debug("Session Management: extended session for :" + session.getId() + " to :"
275                                                         + (int) (maxTimeoutTimeMilliSec / 1000));
276                                 }
277                         } catch (Exception e) {
278                                 logger.error("updateSessionExtensions failed to update session timeouts", e);
279                                 // Signal a problem if any one of them fails
280                                 result = false;
281                         }
282
283                 }
284                 return result;
285         }
286
287         /**
288          * TODO: Remove static
289          * 
290          * @param request
291          *            HttpServletRequest
292          * @param userName
293          *            User name
294          * @param pwd
295          *            Password
296          * @param uebKey
297          *            UEB key (application ID)
298          * @param ecompRestURL
299          *            Remote system URL
300          * @param _sessionComm
301          *            Session communication information
302          */
303         public static void handleSessionUpdatesNative(HttpServletRequest request, String userName, String pwd,
304                         String uebKey, String ecompRestURL, SessionCommInf _sessionComm) {
305
306                 if (_sessionComm == null) {
307                         _sessionComm = sessionComm;
308                 }
309                 try {
310                         synchronizeSessionForLastMinuteRequests(request, ecompRestURL, userName, pwd, uebKey, _sessionComm);
311                 } catch (Exception e) {
312                         logger.error("handleSesionUpdatesNative failed", e);
313                 }
314                 resetSessionMaxIdleTimeOut(request);
315         }
316
317         /**
318          * TODO: remove Static
319          * 
320          * @param request
321          *            HttpServletRequest
322          * @param ecompRestURL
323          *            Remote URL
324          * @param userName
325          *            user name
326          * @param pwd
327          *            password
328          * @param uebKey
329          *            UEB key
330          * @param _sessionComm
331          *            session information
332          * @throws JsonProcessingException
333          *             On failure to serialize
334          */
335         public static void synchronizeSessionForLastMinuteRequests(HttpServletRequest request, String ecompRestURL,
336                         String userName, String pwd, String uebKey, SessionCommInf _sessionComm) throws JsonProcessingException {
337
338                 HttpSession session = request.getSession(false);
339                 if (session == null)
340                         return;
341
342                 Object portalSessionSlotCheckObj = session.getServletContext()
343                                 .getAttribute(PortalApiConstants.PORTAL_SESSION_SLOT_CHECK);
344                 Integer portalSessionSlotCheckinMilliSec = 5 * 60 * 1000; // (5 minutes)
345                 if (portalSessionSlotCheckObj != null) {
346                         portalSessionSlotCheckinMilliSec = Integer.valueOf(portalSessionSlotCheckObj.toString());
347                 } else {
348                         portalSessionSlotCheckObj = _sessionComm
349                                         .fetchSessionSlotCheckInterval(new String[] { ecompRestURL, userName, pwd, uebKey });
350                         logger.debug("Fetching Portal Session Slot Object: " + portalSessionSlotCheckObj);
351                         if (portalSessionSlotCheckObj != null) {
352                                 portalSessionSlotCheckinMilliSec = Integer.valueOf(portalSessionSlotCheckObj.toString());
353                                 session.getServletContext().setAttribute(PortalApiConstants.PORTAL_SESSION_SLOT_CHECK,
354                                                 portalSessionSlotCheckinMilliSec);
355                         }
356                 }
357
358                 Object previousToLastAccessTimeObj = session.getAttribute(PortalApiConstants.SESSION_PREVIOUS_ACCESS_TIME);
359                 final long lastAccessedTimeMilliSec = session.getLastAccessedTime();
360                 if (previousToLastAccessTimeObj == null) {
361                         previousToLastAccessTimeObj = lastAccessedTimeMilliSec;
362                         session.setAttribute(PortalApiConstants.SESSION_PREVIOUS_ACCESS_TIME, previousToLastAccessTimeObj);
363                 } else {
364                         Long previousToLastAccessTime = (Long) previousToLastAccessTimeObj;
365                         final int maxIntervalMilliSec = session.getMaxInactiveInterval() * 1000;
366                         if (maxIntervalMilliSec
367                                         - (lastAccessedTimeMilliSec - previousToLastAccessTime) <= portalSessionSlotCheckinMilliSec) {
368
369                                 String jSessionKey = (String) session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID);
370                                 Map<String, PortalTimeoutVO> sessionTimeoutMap = new Hashtable<>();
371                                 Long sessionTimOutMilliSec = maxIntervalMilliSec + lastAccessedTimeMilliSec;
372
373                                 sessionTimeoutMap.put(PortalTimeoutHandler.portalJSessionId(jSessionKey),
374                                                 PortalTimeoutHandler.getSingleSessionTimeoutObj(jSessionKey, sessionTimOutMilliSec));
375                                 String jsonMap = mapper.writeValueAsString(sessionTimeoutMap);
376                                 logger.debug("Extension requested for all the Apps and Portal;  JessionKey: " + jSessionKey
377                                                 + "; SessionMap: " + sessionTimeoutMap);
378                                 _sessionComm.extendSessionTimeOuts(new String[] { ecompRestURL, userName, pwd, uebKey, jsonMap });
379                         }
380
381                 }
382         }
383
384         /**
385          * TODO: remove static
386          * 
387          * @param request
388          *            HttpServletRequest
389          */
390         public static void resetSessionMaxIdleTimeOut(HttpServletRequest request) {
391                 try {
392                         HttpSession session = request.getSession(false);
393                         if (session == null)
394                                 return;
395                         final Object maxIdleAttribute = session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME);
396                         if (maxIdleAttribute != null) {
397                                 session.setMaxInactiveInterval(Integer.parseInt(maxIdleAttribute.toString()));
398                         }
399                 } catch (Exception e) {
400                         logger.error("resetSessionMaxIdleTimeout failed", e);
401                 }
402
403         }
404
405         /**
406          * 
407          * @param jSessionKey
408          * @param sessionTimOutMilliSec
409          * @return
410          */
411         private static PortalTimeoutVO getSingleSessionTimeoutObj(String jSessionKey, Long sessionTimOutMilliSec) {
412                 return new PortalTimeoutVO(jSessionId(jSessionKey), sessionTimOutMilliSec);
413         }
414
415         /**
416          * 
417          * @param jSessionId
418          * @param portalJSessionId
419          * @return
420          */
421         private static String jSessionKey(String jSessionId, String portalJSessionId) {
422                 return portalJSessionId + "-" + jSessionId;
423         }
424
425         /**
426          * 
427          * @param jSessionKey
428          * @return
429          */
430         private static String portalJSessionId(String jSessionKey) {
431                 return jSessionKey.split("-")[0];
432         }
433
434         /**
435          * 
436          * @param jSessionKey
437          * @return
438          */
439         private static String jSessionId(String jSessionKey) {
440                 return jSessionKey.split("-")[1];
441         }
442
443 }