Copied from DatabaseHashMap.pollForInvalidSessionsWithListeners and DatabaseHashMap.processInvalidListeners.
This method determines the set of sessions with session listeners which
need to be invalidated and processes them.
345563
@FFDCIgnore(Exception.class) //manually logged or is NoSuchElementException which we want to ignore
    private void processInvalidListeners() {
        final boolean trace = com.ibm.websphere.ras.TraceComponent.isAnyTracingEnabled();

        String appName = getIStore().getId();

        long start = System.currentTimeMillis();

        if (trace && tc.isDebugEnabled())
            tcInvoke(tcSessionMetaCache, "iterator");

        @SuppressWarnings("rawtypes")
        Iterator<Cache.Entry<String, ArrayList>> it = sessionMetaCache.iterator();

        if (trace && tc.isDebugEnabled())
            tcReturn(tcSessionMetaCache, "iterator", it);

        while (it.hasNext()) {
            if (trace && tc.isDebugEnabled())
                tcInvoke(tcSessionMetaCache, "_iterator.next");

            @SuppressWarnings("rawtypes")
            Cache.Entry<String, ArrayList> entry;
            try {
                entry = it.next();
            } catch (NoSuchElementException x) {
                // ignore - some JCache providers might raise this instead of returning null when modified during iterator
                entry = null;
            }
            String id = entry == null ? null : entry.getKey();
            ArrayList<?> value = id == null ? null : entry.getValue();

            if (trace && tc.isDebugEnabled())
                tcReturn(tcSessionMetaCache, "_iterator.next", id, value);

            if (id != null && !INVAL_KEY.equals(id)) {
                SessionInfo sessionInfo = new SessionInfo(value);
                long lastAccess = sessionInfo.getLastAccess();
                short listenerTypes = sessionInfo.getListenerTypes();
                int maxInactive = sessionInfo.getMaxInactiveTime();
                if ((listenerTypes & BackedSession.HTTP_SESSION_BINDING_LISTENER) != 0 // sessions that DO have binding listeners
                                && maxInactive >= 0
                                && maxInactive < (start - lastAccess) / 1000) {

                    if (trace && tc.isDebugEnabled())
                        Tr.debug(this, tc, "processInvalidListeners for sessionID=" + id);

                    CacheSession session = new CacheSession(this, id, _iStore.getStoreCallback());
                    session.initSession(_iStore);
                    session.setIsValid(true);
                    session.setIsNew(false);
                    session.updateLastAccessTime(lastAccess);
                    session.setCreationTime(sessionInfo.getCreationTime());
                    session.internalSetMaxInactive(maxInactive);
                    session.internalSetUser(sessionInfo.getUser());
                    session.setListenerFlag(listenerTypes);

                    long now = System.currentTimeMillis();
                    //handle the subset of session listeners

                    lastAccess = session.getCurrentAccessTime(); // try using lastTouch again..

                    try {
                        // get the session ready and read in any listeners
                        session.setIsNew(false);
                        session.getSwappableListeners(BackedSession.HTTP_SESSION_BINDING_LISTENER);

                        sessionInfo = sessionInfo.clone();
                        sessionInfo.setLastAccess(lastAccess);

                        // only invalidate those which have not been accessed since
                        // check in computeInvalidList

                        ArrayList<Object> list = sessionInfo.getArrayList();

                        if (trace && tc.isDebugEnabled())
                            tcInvoke(tcSessionMetaCache, "remove", id, list);

                        boolean removed = sessionMetaCache.remove(id, list);

                        if (trace && tc.isDebugEnabled())
                            tcReturn(tcSessionMetaCache, "remove", removed);

                        if (removed) {
                            // return of session done as a result of this call
                            session.internalInvalidate(true);

                            Set<String> propIds = sessionInfo.getSessionPropertyIds();
                            if (propIds != null && !propIds.isEmpty()) {
                                HashSet<String> propKeys = new HashSet<String>();
                                for (String propId : propIds)
                                    propKeys.add(createSessionAttributeKey(id, propId));

                                if (trace && tc.isDebugEnabled())
                                    tcInvoke(tcSessionAttrCache, "removeAll", propKeys);

                                sessionAttributeCache.removeAll(propKeys);

                                if (trace && tc.isDebugEnabled())
                                    tcReturn(tcSessionAttrCache, "removeAll");
                            }
                        }

                        /*
                         * we don't want to update this on every invalidation with a listener that is processed.
                         * We'll only update this if we're getting close.
                         *
                         * Processing Invalidation Listeners could take a long time. We should update the
                         * NukerTimeStamp so that another server in this cluster doesn't kick off invalidation
                         * while we are still processing. We only want to update the time stamp if we are getting
                         * close to the time when it will expire. Therefore, we are going to do it after we're 1/2 way there.
                         */
                        if ((now + _smc.getInvalidationCheckInterval() * (1000 / 2)) < System.currentTimeMillis()) {
                            updateNukerTimeStamp(appName);
                            now = System.currentTimeMillis();
                        }
                    } catch (Exception e) {
                        FFDCFilter.processException(e, getClass().getName(), "652", this, new Object[] { session });
                        throw e;
                    }
                }
            }
        }
    }
222930
@Override
    public void invalidate() {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
            Tr.event(tc, "Invalidating session; " + this);
        }
        this.valid = false;
        destroy();
    }
458522
public void removeEventListener(EventListener listener)
    {
        if (listener instanceof HttpSessionAttributeListener)
            _sessionAttributeListeners.remove(listener);
        if (listener instanceof HttpSessionListener)
            _sessionListeners.remove(listener);
    }
1025410
private static function _processValidators()
    {
        foreach ($_SESSION['__KWF']['VALID'] as $validator_name => $valid_data) {
            $validator = new $validator_name;
            if ($validator->validate() === false) {
                $_SESSION = array();
                Zend_Session::regenerateId();
                break;
            }
        }
    }
580951
private void invalidateSession(HttpServletRequest req) {
        HttpSession session = req.getSession(false);
        if (session != null) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                Tr.debug(tc, "invalidating existing HTTP Session");
            session.invalidate();
        } else {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                Tr.debug(tc, "Existing HTTP Session does not exist, nothing to invalidate");
        }
    }
1035259
private void process(ImmutableSetMultimap<Class<? extends Annotation>, Element> validElements) {
    for (ProcessingStep step : steps) {
      ImmutableSetMultimap<Class<? extends Annotation>, Element> stepElements =
          new ImmutableSetMultimap.Builder<Class<? extends Annotation>, Element>()
              .putAll(indexByAnnotation(elementsDeferredBySteps.get(step), step.annotations()))
              .putAll(filterKeys(validElements, Predicates.<Object>in(step.annotations())))
              .build();
      if (stepElements.isEmpty()) {
        elementsDeferredBySteps.removeAll(step);
      } else {
        Set<? extends Element> rejectedElements = step.process(stepElements);
        elementsDeferredBySteps.replaceValues(
            step,
            transform(
                rejectedElements,
                new Function<Element, ElementName>() {
                  @Override
                  public ElementName apply(Element element) {
                    return ElementName.forAnnotatedElement(element);
                  }
                }));
      }
    }
  }
816896
@SuppressWarnings("unchecked")
    private String checkForListeners(WebAppConfig config) {
        String listenerFound = NO_LISTENER_REGISTERED_STRING;
        if (config != null) {
            List listeners = config.getListeners();
            for (Object listener : listeners) {
                String listenerClassname;
                /*
                 * if(listener instanceof JavaClassImpl)
                 * listenerClassname = ((JavaClassImpl)listener).getQualifiedName();
                 * else
                 */if (listener instanceof String)
                    listenerClassname = (String) listener;
                else
                    continue; //skip this listener
                if (listenerClassname.equals(SUN_CONFIGURE_LISTENER_CLASSNAME)) {
                    listenerFound = SUN_LISTENER_REGISTERED_STRING;
                    break;
                } else if (listenerClassname.equals(MYFACES_LIFECYCLE_LISTENER_CLASSNAME)) {
                    listenerFound = MYFACES_LISTENER_REGISTERED_STRING;
                    break;
                }
            }
        }
        return listenerFound;
    }
773193
protected void doExecuteListener(Session session, List<Message> messages) throws JMSException {
        if (!isAcceptMessagesWhileStopping() && !isRunning()) {
            if (logger.isWarnEnabled()) {
                logger.warn("Rejecting received messages because of the listener container "
                        + "having been stopped in the meantime: " + messages);
            }
            rollbackIfNecessary(session);
            throw new MessageRejectedWhileStoppingException();
        }

        try {
            for (Message message : messages) {
                invokeListener(session, message);
            }
        } catch (JMSException ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        } catch (RuntimeException ex) {
            rollbackOnExceptionIfNecessary(session, ex);
            throw ex;
        } catch (Error err) {
            rollbackOnExceptionIfNecessary(session, err);
            throw err;
        }
        commitIfNecessary(session, messages);
    }
386893
private void processExternalListeners() {
    List<Class<?>> externalListeners = getAllExternalListeners();
    for (Class<?> externalListener : externalListeners) {
      processExternalListener(externalListener);
    }
  }
612861
@Override
    public boolean isRequestedSessionIDValid(String sessionID, int version) {
        boolean isValid = false;
        if (sessionID != null) {
            ISession session = (ISession) getSession(sessionID, version, false, null);
            if (session != null) {
                isValid = session.isValid();
            }
        }
        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
            LoggingUtil.SESSION_LOGGER_CORE.logp(Level.FINE, methodClassName, "isRequestedSessionIDValid", "" + isValid);
        }
        return isValid;
    }
904228
@Override
    protected void addHttpSessionIdListeners(ArrayList sessionIdListeners, String j2eeName, SessionContext sessCtx) {
        sessCtx.addHttpSessionIdListener(sessionIdListeners, j2eeName);
    }
484496
@Override
    public synchronized void invalidate() {

        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
            LoggingUtil.SESSION_LOGGER_CORE.entering(methodClassName, methodNames[INVALIDATE], appNameAndIdString);
        }
        if (invalInProgress) {
            if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
                LoggingUtil.SESSION_LOGGER_CORE.exiting(methodClassName, methodNames[INVALIDATE], "Invalidation in Progress");
            }
            return;
        }
        if (!_isValid) {
            throw new IllegalStateException();
        }
        invalInProgress = true;
        
        // PM03375: Remove duplicate call to sessionCacheDiscard for persistence case
        if (_smc.isUsingMemory()) {
            _storeCallback.sessionCacheDiscard(this);
        }
        _storeCallback.sessionInvalidated(this);
        _store.removeSession(_sessionId);

        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
            LoggingUtil.SESSION_LOGGER_CORE.logp(Level.FINE, methodClassName, methodNames[INVALIDATE], "_removeAttrOnInvalidate = " + _removeAttrOnInvalidate );
            if(_attributes != null) {
                LoggingUtil.SESSION_LOGGER_CORE.logp(Level.FINE, methodClassName, methodNames[INVALIDATE], "session _attributes.size() = " + _attributes.size() );
            }
        }        
        
        //CTS defect expects removal of session attributes
        if(_attributes != null && _removeAttrOnInvalidate) {
            
           Enumeration<String> attrKey =  _attributes.keys();
           while(attrKey.hasMoreElements()){
               
               String key = attrKey.nextElement();
               this.removeAttribute(key);
           }                    
           if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
               LoggingUtil.SESSION_LOGGER_CORE.logp(Level.FINE, methodClassName, methodNames[INVALIDATE], "session attributes removed");
           }
        }

        setIsValid(false);

        invalInProgress = false;
        _attributes = null;
        _attributeNames.clear();
        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && LoggingUtil.SESSION_LOGGER_CORE.isLoggable(Level.FINE)) {
            LoggingUtil.SESSION_LOGGER_CORE.exiting(methodClassName, methodNames[INVALIDATE]);
        }
    }
112477
@Override
    protected void checkForSessionIdListenerAndAdd(Object listener){
        // Added for Servlet 3.1 support
        if (isHttpSessionIdListener(listener)) {
            // add to the HttpSessionIdListener list
            ((IHttpSessionContext31)this.sessionCtx).addHttpSessionIdListener((javax.servlet.http.HttpSessionIdListener) listener, name);
            this.sessionIdListeners.add(listener);
        }
    }
279155
protected void checkValidForWrite() throws IllegalStateException {
        checkLocked();

        if (state == State.INVALID) {
            throw new IllegalStateException("Not valid for write: session " + this);
        }
        if (state == State.INVALIDATING) {
            return;  // in the process of being invalidated, listeners may try to remove attributes
        }
        if (!isResident()) {
            throw new IllegalStateException("Not valid for write: session " + this);
        }
    }
857123
private void addHttpSessionIdListener(HttpSessionIdListener listener, boolean securityCheckNeeded) throws SecurityException {
        if (securityCheckNeeded) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(perm);
            }
        }
        
        ((IHttpSessionContext31)this.getSessionContext()).addHttpSessionIdListener(listener, name);
    }
714094
private void processMethods() {
    Method[] methods = listenerClass.getDeclaredMethods();
    for (Method method : methods) {
      for (CallbackType callbackType : CallbackType.values()) {
        if (method.isAnnotationPresent(callbackType.getAnnotationClass())) {
          validateMethod(method, callbackType);
          metadata.putListener(callbackType, method);
        }
      }
    }
  }
22030
private List<String> processAllListeners(View rootView) {
        List<String> refinementAttributes = new ArrayList<>();

        // Register any AlgoliaResultsListener (unless it has a different variant than searcher)
        final List<AlgoliaResultsListener> resultListeners = LayoutViews.findByClass((ViewGroup) rootView, AlgoliaResultsListener.class);
        if (resultListeners.isEmpty()) {
            throw new IllegalStateException(Errors.LAYOUT_MISSING_RESULT_LISTENER);
        }
        for (AlgoliaResultsListener listener : resultListeners) {
            if (!this.resultListeners.contains(listener)) {
                final String variant = BindingHelper.getVariantForView((View) listener);
                if (variant == null || searcher.variant.equals(variant)) {
                    this.resultListeners.add(listener);
                    searcher.registerResultListener(listener);
                    prepareWidget(listener, refinementAttributes);
                }
            }
        }

        // Register any AlgoliaErrorListener (unless it has a different variant than searcher)
        final List<AlgoliaErrorListener> errorListeners = LayoutViews.findByClass((ViewGroup) rootView, AlgoliaErrorListener.class);
        for (AlgoliaErrorListener listener : errorListeners) {
            if (!this.errorListeners.contains(listener)) {
                final String variant = BindingHelper.getVariantForView((View) listener);
                if (variant == null || searcher.variant.equals(variant)) {
                    this.errorListeners.add(listener);
                }
            }
            searcher.registerErrorListener(listener);
            prepareWidget(listener, refinementAttributes);
        }

        // Register any AlgoliaSearcherListener (unless it has a different variant than searcher)
        final List<AlgoliaSearcherListener> searcherListeners = LayoutViews.findByClass((ViewGroup) rootView, AlgoliaSearcherListener.class);
        for (AlgoliaSearcherListener listener : searcherListeners) {
            final String variant = BindingHelper.getVariantForView((View) listener);
            if (variant == null || searcher.variant.equals(variant)) {
                listener.initWithSearcher(searcher);
                prepareWidget(listener, refinementAttributes);
            }
        }

        return refinementAttributes;
    }