/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina;

import java.beans.PropertyChangeListener;
import java.io.IOException;

/**
 * A <b>Manager</b> manages the pool of Sessions that are associated with a particular Context. Different Manager
 * implementations may support value-added features such as the persistent storage of session data, as well as migrating
 * sessions for distributable web applications.
 * <p>
 * In order for a <code>Manager</code> implementation to successfully operate with a <code>Context</code> implementation
 * that implements reloading, it must obey the following constraints:
 * <ul>
 * <li>Must implement <code>Lifecycle</code> so that the Context can indicate that a restart is required.
 * <li>Must allow a call to <code>stop()</code> to be followed by a call to <code>start()</code> on the same
 * <code>Manager</code> instance.
 * </ul>
 */
public interface Manager {

    // ------------------------------------------------------------- Properties

    /**
     * Get the Context with which this Manager is associated.
     *
     * @return The associated Context
     */
    Context getContext();


    /**
     * Set the Context with which this Manager is associated. The Context must be set to a non-null value before the
     * Manager is first used. Multiple calls to this method before first use are permitted. Once the Manager has been
     * used, this method may not be used to change the Context (including setting a {@code null} value) that the Manager
     * is associated with.
     *
     * @param context The newly associated Context
     */
    void setContext(Context context);


    /**
     * Returns the session id generator for this manager.
     *
     * @return the session id generator
     */
    SessionIdGenerator getSessionIdGenerator();


    /**
     * Sets the session id generator
     *
     * @param sessionIdGenerator The session id generator
     */
    void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator);


    /**
     * Returns the total number of sessions created by this manager, which is approximated as the number of active
     * sessions plus the number of expired sessions.
     *
     * @return Total number of sessions created by this manager.
     */
    long getSessionCounter();


    /**
     * Gets the maximum number of sessions that have been active at the same time.
     *
     * @return Maximum number of sessions that have been active at the same time
     */
    int getMaxActive();


    /**
     * (Re)sets the maximum number of sessions that have been active at the same time.
     *
     * @param maxActive Maximum number of sessions that have been active at the same time.
     */
    void setMaxActive(int maxActive);


    /**
     * Gets the number of currently active sessions.
     *
     * @return Number of currently active sessions
     */
    int getActiveSessions();


    /**
     * Gets the number of sessions that have expired.
     *
     * @return Number of sessions that have expired
     */
    long getExpiredSessions();


    /**
     * Sets the number of sessions that have expired.
     *
     * @param expiredSessions Number of sessions that have expired
     */
    void setExpiredSessions(long expiredSessions);


    /**
     * Gets the number of sessions that were not created because the maximum number of active sessions was reached.
     *
     * @return Number of rejected sessions
     */
    int getRejectedSessions();


    /**
     * Gets the longest time (in seconds) that an expired session had been alive.
     *
     * @return Longest time (in seconds) that an expired session had been alive.
     */
    int getSessionMaxAliveTime();


    /**
     * Sets the longest time (in seconds) that an expired session had been alive.
     *
     * @param sessionMaxAliveTime Longest time (in seconds) that an expired session had been alive.
     */
    void setSessionMaxAliveTime(int sessionMaxAliveTime);


    /**
     * Gets the average time (in seconds) that expired sessions had been alive. This may be based on sample data.
     *
     * @return Average time (in seconds) that expired sessions had been alive.
     */
    int getSessionAverageAliveTime();


    /**
     * Gets the current rate of session creation (in session per minute). This may be based on sample data.
     *
     * @return The current rate (in sessions per minute) of session creation
     */
    int getSessionCreateRate();


    /**
     * Gets the current rate of session expiration (in session per minute). This may be based on sample data
     *
     * @return The current rate (in sessions per minute) of session expiration
     */
    int getSessionExpireRate();


    // --------------------------------------------------------- Public Methods

    /**
     * Add this Session to the set of active Sessions for this Manager.
     *
     * @param session Session to be added
     */
    void add(Session session);


    /**
     * Add a property change listener to this component.
     *
     * @param listener The listener to add
     */
    void addPropertyChangeListener(PropertyChangeListener listener);


    /**
     * Change the session ID of the current session to a new randomly generated session ID.
     *
     * @param session The session to change the session ID for
     *
     * @return The new session ID
     */
    default String rotateSessionId(Session session) {
        String newSessionId = getSessionIdGenerator().generateSessionId();
        changeSessionId(session, newSessionId);
        return newSessionId;
    }


    /**
     * Change the session ID of the current session to a specified session ID.
     *
     * @param session The session to change the session ID for
     * @param newId   new session ID
     */
    void changeSessionId(Session session, String newId);


    /**
     * Get a session from the recycled ones or create a new empty one. The PersistentManager manager does not need to
     * create session data because it reads it from the Store.
     *
     * @return An empty Session object
     */
    Session createEmptySession();


    /**
     * Construct and return a new session object, based on the default settings specified by this Manager's properties.
     * The session id specified will be used as the session id. If a new session cannot be created for any reason,
     * return <code>null</code>.
     *
     * @param sessionId The session id which should be used to create the new session; if <code>null</code>, the session
     *                      id will be assigned by this method, and available via the getId() method of the returned
     *                      session.
     *
     * @exception IllegalStateException if a new session cannot be instantiated for any reason
     *
     * @return An empty Session object with the given ID or a newly created session ID if none was specified
     */
    Session createSession(String sessionId);


    /**
     * Return the active Session, associated with this Manager, with the specified session id (if any); otherwise return
     * <code>null</code>.
     *
     * @param id The session id for the session to be returned
     *
     * @exception IllegalStateException if a new session cannot be instantiated for any reason
     * @exception IOException           if an input/output error occurs while processing this request
     *
     * @return the request session or {@code null} if a session with the requested ID could not be found
     */
    Session findSession(String id) throws IOException;


    /**
     * Return the set of active Sessions associated with this Manager. If this Manager has no active Sessions, a
     * zero-length array is returned.
     *
     * @return All the currently active sessions managed by this manager
     */
    Session[] findSessions();


    /**
     * Load any currently active sessions that were previously unloaded to the appropriate persistence mechanism, if
     * any. If persistence is not supported, this method returns without doing anything.
     *
     * @exception ClassNotFoundException if a serialized class cannot be found during the reload
     * @exception IOException            if an input/output error occurs
     */
    void load() throws ClassNotFoundException, IOException;


    /**
     * Remove this Session from the active Sessions for this Manager.
     *
     * @param session Session to be removed
     */
    void remove(Session session);


    /**
     * Remove this Session from the active Sessions for this Manager.
     *
     * @param session Session to be removed
     * @param update  Should the expiration statistics be updated
     */
    void remove(Session session, boolean update);


    /**
     * Remove a property change listener from this component.
     *
     * @param listener The listener to remove
     */
    void removePropertyChangeListener(PropertyChangeListener listener);


    /**
     * Save any currently active sessions in the appropriate persistence mechanism, if any. If persistence is not
     * supported, this method returns without doing anything.
     *
     * @exception IOException if an input/output error occurs
     */
    void unload() throws IOException;


    /**
     * This method will be invoked by the context/container on a periodic basis and allows the manager to implement a
     * method that executes periodic tasks, such as expiring sessions etc.
     */
    void backgroundProcess();


    /**
     * Would the Manager distribute the given session attribute? Manager implementations may provide additional
     * configuration options to control which attributes are distributable.
     *
     * @param name  The attribute name
     * @param value The attribute value
     *
     * @return {@code true} if the Manager would distribute the given attribute otherwise {@code false}
     */
    boolean willAttributeDistribute(String name, Object value);


    /**
     * When an attribute that is already present in the session is added again under the same name and the attribute
     * implements {@link jakarta.servlet.http.HttpSessionBindingListener}, should
     * {@link jakarta.servlet.http.HttpSessionBindingListener#valueUnbound(jakarta.servlet.http.HttpSessionBindingEvent)}
     * be called followed by
     * {@link jakarta.servlet.http.HttpSessionBindingListener#valueBound(jakarta.servlet.http.HttpSessionBindingEvent)}?
     * <p>
     * The default value is {@code false}.
     *
     * @return {@code true} if the listener will be notified, {@code false} if it will not
     */
    default boolean getNotifyBindingListenerOnUnchangedValue() {
        return false;
    }


    /**
     * Configure if
     * {@link jakarta.servlet.http.HttpSessionBindingListener#valueUnbound(jakarta.servlet.http.HttpSessionBindingEvent)}
     * be called followed by
     * {@link jakarta.servlet.http.HttpSessionBindingListener#valueBound(jakarta.servlet.http.HttpSessionBindingEvent)}
     * when an attribute that is already present in the session is added again under the same name and the attribute
     * implements {@link jakarta.servlet.http.HttpSessionBindingListener}.
     *
     * @param notifyBindingListenerOnUnchangedValue {@code true} the listener will be called, {@code
     *                                              false} it will not
     */
    void setNotifyBindingListenerOnUnchangedValue(boolean notifyBindingListenerOnUnchangedValue);


    /**
     * When an attribute that is already present in the session is added again under the same name and a
     * {@link jakarta.servlet.http.HttpSessionAttributeListener} is configured for the session should
     * {@link jakarta.servlet.http.HttpSessionAttributeListener#attributeReplaced(jakarta.servlet.http.HttpSessionBindingEvent)}
     * be called?
     * <p>
     * The default value is {@code true}.
     *
     * @return {@code true} if the listener will be notified, {@code false} if it will not
     */
    default boolean getNotifyAttributeListenerOnUnchangedValue() {
        return true;
    }


    /**
     * Configure if
     * {@link jakarta.servlet.http.HttpSessionAttributeListener#attributeReplaced(jakarta.servlet.http.HttpSessionBindingEvent)}
     * when an attribute that is already present in the session is added again under the same name and a
     * {@link jakarta.servlet.http.HttpSessionAttributeListener} is configured for the session.
     *
     * @param notifyAttributeListenerOnUnchangedValue {@code true} the listener will be called, {@code
     *                                                false} it will not
     */
    void setNotifyAttributeListenerOnUnchangedValue(boolean notifyAttributeListenerOnUnchangedValue);


    /**
     * If this is <code>true</code>, Tomcat will track the number of active requests for each session. When determining
     * if a session is valid, any session with at least one active request will always be considered valid. If
     * <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code> is set to <code>true</code>, the default of this
     * setting will be <code>true</code>, else the default value will be <code>false</code>.
     *
     * @return the flag value
     */
    default boolean getSessionActivityCheck() {
        return Globals.STRICT_SERVLET_COMPLIANCE;
    }


    /**
     * Configure if Tomcat will track the number of active requests for each session. When determining if a session is
     * valid, any session with at least one active request will always be considered valid.
     *
     * @param sessionActivityCheck the new flag value
     */
    void setSessionActivityCheck(boolean sessionActivityCheck);


    /**
     * If this is <code>true</code>, the last accessed time for sessions will be calculated from the beginning of the
     * previous request. If <code>false</code>, the last accessed time for sessions will be calculated from the end of
     * the previous request. This also affects how the idle time is calculated. If
     * <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code> is set to <code>true</code>, the default of this
     * setting will be <code>true</code>, else the default value will be <code>false</code>.
     *
     * @return the flag value
     */
    default boolean getSessionLastAccessAtStart() {
        return Globals.STRICT_SERVLET_COMPLIANCE;
    }


    /**
     * Configure if the last accessed time for sessions will be calculated from the beginning of the previous request.
     * If <code>false</code>, the last accessed time for sessions will be calculated from the end of the previous
     * request. This also affects how the idle time is calculated.
     *
     * @param sessionLastAccessAtStart the new flag value
     */
    void setSessionLastAccessAtStart(boolean sessionLastAccessAtStart);

}
