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