package com.atlassian.stash.internal.hazelcast;

import com.atlassian.hazelcast.serialization.OsgiSafe;
import com.hazelcast.web.HazelcastHttpSession;
import com.hazelcast.web.WebFilter;

import javax.servlet.http.HttpSession;
import java.util.Properties;

import static com.atlassian.cache.hazelcast.OsgiSafeUtils.unwrap;
import static com.atlassian.cache.hazelcast.OsgiSafeUtils.wrap;

/**
 * Extends Hazelcast's {@code WebFilter} in two ways. It allows injecting the {@code HazelcastInstance} rather than
 * constructing one from some other configuration location. This is intended to allow using a single
 * {@code HazelcastInstance} for the entire system.
 * <p>
 * This extension also overrides Hazelcast's standard {@code HazelcastHttpSession} with a version that wraps all
 * session attributes in {@link com.atlassian.hazelcast.serialization.OsgiSafe} wrappers to allow plugins to safely
 * store attributes in the session without running into class loading issue.
 *
 * @since 3.2
 */
public class ExtendedWebFilter extends WebFilter {

    private final boolean stickySession;

    public ExtendedWebFilter(Properties properties) {
        super(properties);
        this.stickySession = Boolean.parseBoolean(properties.getProperty("sticky-session"));
    }

    @Override
    protected HazelcastHttpSession createHazelcastHttpSession(String sessionId, HttpSession originalSession, boolean deferredWrite) {
        return new OsgiSafeHazelcastHttpSession(sessionId, originalSession, deferredWrite, stickySession);
    }

    /**
     * Extends Hazelcast's {@code HazelcastHttpSession} to wrap all attributes in an {@link OsgiSafe} wrapper. This
     * ensures plugins can store their data in the session without running into class loading issues.
     *
     * @since 3.3
     */
    protected class OsgiSafeHazelcastHttpSession extends HazelcastHttpSession {

        public OsgiSafeHazelcastHttpSession(String sessionId, HttpSession originalSession, boolean deferredWrite,
                                            boolean stickySession) {
            super(ExtendedWebFilter.this, sessionId, originalSession, deferredWrite, stickySession);
        }

        @Override
        public Object getAttribute(String name) {
            return unwrap((OsgiSafe) super.getAttribute(name));
        }

        @Override
        public void setAttribute(String name, Object value) {
            super.setAttribute(name, wrap(value));
        }
    }
}