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