/*
Need to override this method because we need access to HttpSessionIdListener.
(non-Javadoc)
@see com.ibm.ws.webcontainer.webapp.WebApp#commonAddListener(java.lang.String, java.util.EventListener, java.lang.Class)
765750
@Override
    public void commonAddListener(String listenerClassName, EventListener listener,
                                  Class<? extends EventListener> listenerClass) {
        
        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && logger.isLoggable(Level.FINE))
            logger.entering(CLASS_NAME, "commonAddListener : listenerClassName = " + listenerClassName  
                                                             + ", listener = " + (listener==null ? "null" : listener.getClass().getName()) 
                                                             + ", listenerClass = " + (listenerClass==null ? "null" : listenerClass.getName()));
        if (initialized) {
            throw new IllegalStateException(liberty_nls.getString("Not.in.servletContextCreated"));
        }
        if (withinContextInitOfProgAddListener) {
            throw new UnsupportedOperationException(nls.getString("Unsupported.op.from.servlet.context.listener"));
        }
        if (com.ibm.ws.webcontainer.osgi.WebContainer.isServerStopping()) {
            return;
        }
        Class className = listenerClass;
        try {
            if (listenerClassName != null) {
                className = Class.forName(listenerClassName, true, this.getClassLoader());
            } else if (listener != null) {
                className = listener.getClass();
            }
            Class[] validListenerClasses = new Class[7];
            validListenerClasses[0] = javax.servlet.ServletContextAttributeListener.class;
            validListenerClasses[1] = javax.servlet.ServletRequestListener.class;
            validListenerClasses[2] = javax.servlet.ServletRequestAttributeListener.class;
            validListenerClasses[3] = javax.servlet.http.HttpSessionListener.class;
            validListenerClasses[4] = javax.servlet.http.HttpSessionAttributeListener.class;
            validListenerClasses[5] = javax.servlet.http.HttpSessionIdListener.class;


                //if this was called from ServletContainerInitializer#onStartup, then the listener can implement ServletContextListener
            if (canAddServletContextListener) { // changed to protected scope in parent
                validListenerClasses[6] = javax.servlet.ServletContextListener.class;
            } else {
                if ((javax.servlet.ServletContextListener.class).isAssignableFrom(className)) {
                    throw new IllegalArgumentException(nls.getString("Error.adding.ServletContextListener"));
                }
            }
            boolean valid = false;
            Set classesSet = new HashSet();
            for (Class c : validListenerClasses) {
                if (c != null && c.isAssignableFrom(className)) {
                    valid = true;
                    classesSet.add(c);
                }
            }
            if (!valid) {
                throw new IllegalArgumentException(nls.getString("Invalid.Listener"));
            }

            if (listener == null) {
                //processDynamicInjectionMetaData(null, className);

                // Class or className was passed, need to create an instance
                // Injection done here
                try {
                    listener = createListener(className);
                } catch (Exception e) {
                        logger.logp(Level.SEVERE, CLASS_NAME, "commonAddListener", "exception.occurred.while.creating.listener.instance", new Object[] {
                                className, e });
                }
            }
            // add it to the end of the ordered list of listeners
            if (classesSet.contains(javax.servlet.ServletContextAttributeListener.class)) {
                this.servletContextLAttrListeners.add(listener);
            }
            if (classesSet.contains(javax.servlet.ServletRequestListener.class)) {
                this.servletRequestListeners.add(listener);
            }
            if (classesSet.contains(javax.servlet.ServletRequestAttributeListener.class)) {
                this.servletRequestLAttrListeners.add(listener);
            }
            if (classesSet.contains(javax.servlet.http.HttpSessionListener.class)) {
                    this.sessionListeners.add(listener);//add to this list in case we need to do a preDestroy
                    // No need to to HttpSessionListeners if the sessionContext is null because
                    // it will be added when the session context is created.
                    if (this.getSessionContext()!=null)
                        this.addHttpSessionListener((HttpSessionListener) listener, false);
            }
            if (classesSet.contains(javax.servlet.http.HttpSessionAttributeListener.class)) {
                        sessionAttrListeners.add(listener);//add to this list in case we need to do a preDestroy
                this.addHttpSessionAttributeListener((HttpSessionAttributeListener) listener);
            }
            // Added for Servlet 3.1 HttpSessionIdListener support
            if (classesSet.contains(javax.servlet.http.HttpSessionIdListener.class)) {
                sessionIdListeners.add(listener);//add to this list in case we need to do a preDestroy
                this.addHttpSessionIdListener((HttpSessionIdListener) listener);
            }
            if (classesSet.contains(javax.servlet.ServletContextListener.class)) {
                this.servletContextListeners.add(listener);
            }
        } catch (ClassNotFoundException e) {
            // This method can be called from addListener(String) which calls this method with a null
            // value for listenerClass, in turn if a ClassNotFoundException occurs the className is also null 
            // as className is set to = listenerClass before calling Class.forName which can throw the ClassNotFoundException.
            // Due to className having the possibility of being null we can't log className.getName() as an NPE will occur. Also
            // we should be logging listenerClassName as that is the listenerClassName that could not be found.
            logger.logp(Level.SEVERE, CLASS_NAME, "commonAddListener", 
                        "exception.occurred.while.adding.listener", new Object[] {listenerClassName});
        }
        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && logger.isLoggable(Level.FINE))
            logger.exiting(CLASS_NAME, "commomAddListener");
        
    }
128121
public static void addEntityChangeListener(I_CmsEntityChangeListener changeListener, String changeScope) {

        CmsDebugLog.getInstance().printLine("trying to ad change listener for scope: " + changeScope);
        if ((INSTANCE == null) || (INSTANCE.m_entityObserver == null)) {
            CmsDebugLog.getInstance().printLine("handling external registration");
            if (isObserverExported()) {
                CmsDebugLog.getInstance().printLine("registration is available");
                try {
                    addNativeListener(changeListener, changeScope);
                } catch (Exception e) {

                    CmsDebugLog.getInstance().printLine(
                        "Exception occured during listener registration" + e.getMessage());
                }
            } else {
                throw new RuntimeException("Editor is not initialized yet.");
            }
        } else {
            INSTANCE.m_entityObserver.addEntityChangeListener(changeListener, changeScope);
        }
    }
587781
@Nonnull
  public EChange addListener (@Nonnull final EventListener aListener)
  {
    ValueEnforcer.notNull (aListener, "Listener");

    // Small consistency check
    if (!(aListener instanceof ServletContextListener) &&
        !(aListener instanceof HttpSessionListener) &&
        !(aListener instanceof ServletRequestListener))
    {
      LOGGER.warn ("Passed mock listener is none of ServletContextListener, HttpSessionListener or ServletRequestListener and therefore has no effect. The listener class is: " +
                      aListener.getClass ());
    }

    return m_aRWLock.writeLocked ( () -> EChange.valueOf (m_aListener.add (aListener)));
  }
590808
private void commonInit() {
        listenerFlag = HTTP_SESSION_NO_LISTENER;
        deferWriteUntilNextTick = 0;
        mLastWriteTime = -1;
        removingSessionFromCache = false;
        _refCount = 0;
        _version = initialCacheId;
    }
907783
public void addEventListener(EventListener listener)
    throws IllegalArgumentException
    {
        
        if (listener instanceof HttpSessionAttributeListener)
            _sessionAttributeListeners.add(listener);
        if (listener instanceof HttpSessionListener)
            _sessionListeners.add(listener);
    }
1018135
@Override
    public void unregisterInjectionMetaDataListener(InjectionMetaDataListener metaDataListener)
    {
        if (metaDataListener == null) {
            throw new IllegalArgumentException("A null InjectionMetaDataListener cannot be unregistered " +
                                               "from the injection engine.");
        }
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            Tr.entry(tc, "unregisterInjectionMetaDataListener", metaDataListener.getClass().getName());
        metaDataListeners.remove(metaDataListener);
    }
584738
function (args, commonInfo, interceptorIndex) {
        if (interceptorIndex >= commonInfo.nbInterceptors) {
            // end of recursion: call the real method:
            return this[commonInfo.method].apply(this, args);
        }
        var interc = commonInfo.interceptors[interceptorIndex];
        if (interc.removed) {
            // interceptor was removed in the mean time, skip it.
            return __callWrapper.call(this, info.args, commonInfo, interceptorIndex + 1);
        }
        var info = {
            step : "CallBegin",
            method : commonInfo.method,
            args : args,
            cancelDefault : false,
            returnValue : null
        };
        var asyncCbParam = commonInfo.asyncCbParam;
        if (asyncCbParam != null) {
            var callback = {
                fn : __callbackWrapper,
                scope : this,
                args : {
                    info : info,
                    interc : interc,
                    // save previous callback:
                    origCb : args[asyncCbParam]
                }
            };
            args[asyncCbParam] = callback;
            if (args.length <= asyncCbParam) {
                // We do this check and set the length property because the
                // "args" object comes
                // from the JavaScript arguments object, which is not a real
                // array so that the
                // length property is not updated automatically by the previous
                // assignation: args[asyncCbParam] = callback;
                args.length = asyncCbParam + 1;
            }
            info.callback = callback;
        }
        this.$callback(interc, info);
        if (!info.cancelDefault) {
            // call next wrapper or real method:
            try {
                info.returnValue = __callWrapper.call(this, info.args, commonInfo, interceptorIndex + 1);
            } catch (e) {
                info.exception = e;
            }
            info.step = "CallEnd";
            delete info.cancelDefault; // no longer useful in CallEnd
            // call the interceptor, even if it was removed in the mean time (so
            // that CallEnd is always called when
            // CallBegin has been called):
            this.$callback(interc, info);
            if ("exception" in info) {
                throw info.exception;
            }
        }
        return info.returnValue;
    }
1182875
public void addTangoUserListener(ITangoUserListener listener, String attrName, String[] filters)
            throws DevFailed {
        addTangoUserListener(listener, attrName, filters, false);
    }
1274070
@Override
    public void onApplicationEvent(HttpSessionDestroyedEvent event) {
        final HttpSession session = ((HttpSessionDestroyedEvent) event).getSession();
        @SuppressWarnings("unchecked")
        final Map<String, PortletSession> portletSessions =
                (Map<String, PortletSession>) session.getAttribute(PORTLET_SESSIONS_MAP);
        if (portletSessions == null) {
            return;
        }

        /*
         * Since (at least) Tomcat 7.0.47, this method has the potential to
         * generate a StackOverflowError because PortletSession.invalidate()
         * will trigger another HttpSessionDestroyedEvent, which means this
         * method will be called again.  I don't know if this behavior is a bug
         * in Tomcat or Spring, if this behavior is entirely proper, or if the
         * reality somewhere in between.
         *
         * For the present, let's put a token in the HttpSession (which is
         * available from the event object) as soon as we start invalidating it.
         * We'll then ignore sessions that already have this token.
         */
        if (session.getAttribute(ALREADY_INVALIDATING_SESSION_ATTRIBUTE) != null) {
            // We're already invalidating;  don't do it again
            return;
        }
        session.setAttribute(ALREADY_INVALIDATING_SESSION_ATTRIBUTE, Boolean.TRUE);

        for (final Map.Entry<String, PortletSession> portletSessionEntry :
                portletSessions.entrySet()) {
            final String contextPath = portletSessionEntry.getKey();
            final PortletSession portletSession = portletSessionEntry.getValue();
            try {
                portletSession.invalidate();
            } catch (IllegalStateException e) {
                this.logger.info(
                        "PortletSession with id '"
                                + portletSession.getId()
                                + "' for context '"
                                + contextPath
                                + "' has already been invalidated.");
            } catch (Exception e) {
                this.logger.warn(
                        "Failed to invalidate PortletSession with id '"
                                + portletSession.getId()
                                + "' for context '"
                                + contextPath
                                + "'",
                        e);
            }
        }
    }
871055
public synchronized void addEventListener(EventListener listener)
        throws IllegalArgumentException
    {
        if ((listener instanceof HttpSessionActivationListener)
            || (listener instanceof HttpSessionAttributeListener)
            || (listener instanceof HttpSessionBindingListener)
            || (listener instanceof HttpSessionListener))
        {
            if (_sessionManager != null)
                _sessionManager.addEventListener(listener);
            _sessionListeners= LazyList.add(_sessionListeners, listener);
        }

        if (listener instanceof ServletRequestListener)
        {
            _requestListeners= LazyList.add(_requestListeners, listener);
        }

        if (listener instanceof ServletRequestAttributeListener)
        {
             _requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener);
        }

        if (listener instanceof ServletContextAttributeListener)
        {            
            _contextAttributeListeners= LazyList.add(_contextAttributeListeners, listener);
        }
        
        super.addEventListener(listener);
    }
286322
public void addTangoUserListener(ITangoUserListener listener, String attrName, boolean stateless)
            throws DevFailed {
        addTangoUserListener(listener, attrName, new String[0], stateless);
    }
1180882
public void addEventSourceListener(EventSourceListener listener) {
        LOG.entering(CLASS_NAME, "addEventSourceListener", listener);
        if (listener == null) {
            throw new NullPointerException("listener");
        }
        listeners.add(listener);
    }
1008389
public void addLifecycleListener(java.util.EventListener listener) {
        String listenerClassName = getClassName(listener);
        if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && logger.isLoggable(Level.FINE)) {
                logger.entering(CLASS_NAME, "addLifecycleListener : listenerClass = " + listenerClassName);     
        }       

        if (listener != null) {
            if (listener instanceof javax.servlet.ServletContextListener) {
                addServletContextListener(listener);
            }
            if (listener instanceof javax.servlet.ServletContextAttributeListener) {
                // add to the context attr listener list
                servletContextLAttrListeners.add(listener);
            }

            if (listener instanceof javax.servlet.http.HttpSessionListener) {
                // add to the session listener list
                this.sessionCtx.addHttpSessionListener((javax.servlet.http.HttpSessionListener) listener, name);

                // 434577
                // add to a mirror list because we can't get access to the list
                // the
                // session context is holding on to later on.

                this.sessionListeners.add(listener);
                this.addedSessionListeners.add(listener);
            }
            
            // Servlet 3.1
            checkForSessionIdListenerAndAdd(listener);

            // \PK34418 begins
            if (listener instanceof javax.servlet.http.HttpSessionAttributeListener) {
                // add to the session attribute listener list
                if (com.ibm.ejs.ras.TraceComponent.isAnyTracingEnabled() && logger.isLoggable(Level.FINE)) {
                    logger
                            .logp(Level.FINE, CLASS_NAME, "addLifecycleListener",
                                    "listener instanceof javax.servlet.http.HttpSessionAttributeListener");
                    logger.logp(Level.FINE, CLASS_NAME, "addLifecycleListener", "name : " + name);
                }
                this.sessionCtx.addHttpSessionAttributeListener((HttpSessionAttributeListener) listener, name);

                // 434577
                // add to a mirror list because we can't get access to the list
                // the
                // session context is holding on to later on.

                this.sessionAttrListeners.add(listener);
                this.addedSessionAttrListeners.add(listener);

            }// PK34418

            // 2.4 Listeners
            if (listener instanceof javax.servlet.ServletRequestListener) {
                servletRequestListeners.add(listener);
            }
            if (listener instanceof javax.servlet.ServletRequestAttributeListener) {
                servletRequestLAttrListeners.add(listener);
            }

            if (listener instanceof javax.servlet.http.HttpSessionActivationListener) {
                sessionActivationListeners.add(listener);
            }

            if (listener instanceof javax.servlet.http.HttpSessionBindingListener) {
                sessionBindingListeners.add(listener);
            }
        }
        logger.exiting(CLASS_NAME, "addLifecycleListener");
    }
555463
@Override
    public void registerRecoveryEventListener(RecoveryEventListener rel) /* @MD19638A */
    {
        if (tc.isEntryEnabled())
            Tr.entry(tc, "registerRecoveryEventListener", rel);

        RegisteredRecoveryEventListeners.instance().add(rel);

        if (tc.isEntryEnabled())
            Tr.exit(tc, "registerRecoveryEventListener");
    }
569269
@Override
  public void setSessionListener(String sessionId, NetworkReqListener data) {
    if (this.localDataSource.exists(sessionId)) {
      this.localDataSource.setSessionListener(sessionId, data);
    }
    else if (!this.localMode && this.existReplicated(sessionId)) {
      // does not make much sense ;[
      this.makeLocal(sessionId);
      this.localDataSource.setSessionListener(sessionId, data);
    }
  }
976822
private void setAsyncListener(MessageListener listener) throws JMSException {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "setAsyncListener", listener);

        consumer = new Consumer(listener, session, sessionAckMode);
        try {
            // ConsumerSession must be stopped to register the callback
            coreConsumerSession.stop();
            int batchSize = 1;
            boolean deliverImmediately = false;
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                SibTr.debug(this, tc, "Registering async callback for consumer" + consumer);
            // the register call will replace any existing callback, so no need for
            // separate deregister call.
            coreConsumerSession.registerAsynchConsumerCallback(consumer,
                                                               0, // maxActiveMessages - no limit
                                                               0, // messageLockExpiry - no expiry
                                                               batchSize,
                                                               session.getOrderingContext()
                            );

            // Deal with the case where the listener is set after the connection
            // is started. Note that this will handle the restarting of the core
            // consumer session if we paused it earlier in this block.
            if (session.getState() == STARTED)
                coreConsumerSession.start(deliverImmediately);
        } catch (SIIncorrectCallException sie) {
            // No FFDC code needed
            // d222942 review. Default message ok.
            // d238447 FFDC Review. FFDC here, see comment in next catch for more detail.
            throw (JMSException) JmsErrorUtils.newThrowable(JMSException.class,
                                                            "EXCEPTION_RECEIVED_CWSIA0085",
                                                            new Object[] { sie, "JmsMsgConsumerImpl.setAsyncListener" },
                                                            sie,
                                                            "JmsMsgConsumerImpl.setAsyncListener#1",
                                                            this,
                                                            tc);
        } catch (SIException sie) {
            // No FFDC code needed
            // The exceptions thrown by stop, registerAsynchConsumerCallback and start are mostly
            // the "connection lost" family. registerAsynchConsumerCallback can also throw an
            // SIIncorrectCallException if the coreConsumerSession hasn't been stopped, but that
            // shouldn't be possible in the code above. Default message ok.
            // d238447 FFDC Review. SIIncorrectCall separated into its own catch block above,
            //   no FFDCs for this group.
            throw (JMSException) JmsErrorUtils.newThrowable(JMSException.class,
                                                            "EXCEPTION_RECEIVED_CWSIA0085",
                                                            new Object[] { sie, "JmsMsgConsumerImpl.setAsyncListener" },
                                                            sie,
                                                            null, // null probeId = no FFDC
                                                            this,
                                                            tc);
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(this, tc, "setAsyncListener");
    }
1320738
@Override
    public synchronized void addChainEventListener(ChainEventListener cel, String chainName) throws InvalidChainNameException {
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
            Tr.debug(tc, "addChainEventListener: chain=" + chainName + " listener=" + cel);
        }
        ChainDataImpl chainData = null;

        if (null == chainName) {
            InvalidChainNameException e = new InvalidChainNameException("Unable to register a listener for a chain with null name");
            //Race condition can occur where chain is stopped before we register the listener, no need to FFDC
            //FFDCFilter.processException(e, getClass().getName() + ".addChainEventListener", "2910", this, new Object[] { chainName, this });
            throw e;
        }

        // Handle a listener registering for events from all chains.
        if (chainName.equals(ChainEventListener.ALL_CHAINS)) {
            for (ChainData chain : this.chainDataMap.values()) {
                ((ChainDataImpl) chain).addChainEventListener(cel);
            }
            this.globalChainEventListeners.add(cel);
        } else {
            // Extract the chain config from the framework.
            chainData = this.chainDataMap.get(chainName);
            // Verify the chain config is in the framework
            if (null == chainData) {
                InvalidChainNameException e = new InvalidChainNameException("Unable to register listener for unknown chain config, " + chainName);
                //Race condition can occur where chain is stopped before we register the listener, no need to FFDC
                //FFDCFilter.processException(e, getClass().getName() + ".addChainEventListener", "2910", this, new Object[] { chainName, this });
                throw e;
            }
            chainData.addChainEventListener(cel);
        }
    }