/*
 * Copyright 2005-2008 Les Hazlewood
 *
 * Licensed 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.jsecurity.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsecurity.subject.Subject;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * A ThreadContext provides a means of binding and unbinding objects to the
 * current thread based on key/value pairs.
 *
 * <p>An internal {@link java.util.HashMap} is used to maintain the key/value pairs
 * for each thread.</p>
 *
 * <p>If the desired behavior is to ensure that bound data is not shared across
 * threads in a pooled or reusable threaded environment, the application (or more likely a framework) must
 * bind and remove any necessary values at the beginning and end of stack
 * execution, respectively (i.e. individually explicitly or all via the <tt>clear</tt> method).</p>
 *
 * @see #clear()
 * 
 * @since 0.1
 * @author Les Hazlewood
 */
@SuppressWarnings( value = { "unchecked", "unsafe" } )
public abstract class ThreadContext {

    protected static transient final Log logger = LogFactory.getLog( ThreadContext.class );

    public static final String SUBJECT_KEY = Subject.class.getName() + "_THREAD_CONTEXT_KEY";
    public static final String INET_ADDRESS_KEY = InetAddress.class.getName() + "_JSECURITY_THREAD_CONTEXT_KEY";
    public static final String SERVLET_REQUEST_KEY = ServletRequest.class.getName() + "_JSECURITY_THREAD_CONTEXST_KEY";
    public static final String SERVLET_RESPONSE_KEY = ServletResponse.class.getName() + "_JSECURITY_THREAD_CONTEXT_KEY";

    protected static ThreadLocal<Map<Object, Object>> resources =
        new InheritableThreadLocal<Map<Object, Object>>() {
            protected Map<Object, Object> initialValue() {
                return new HashMap<Object, Object>();
            }
        };

    protected ThreadContext() {
    }

    /**
     * Returns the ThreadLocal Map. This Map is used internally to bind objects
     * to the current thread by storing each object under a unique key.
     *
     * @return the map of bound resources
     */
    protected static Map<Object, Object> getResources() {
        return resources.get();
    }

    /**
     * Returns the object for the specified <code>key</code> that is bound to
     * the current thread.
     *
     * @param key the key that identifies the value to return
     * @return the object keyed by <code>key</code> or <code>null</code> if
     *         no value exists for the specified <code>key</code>
     */
    public static Object get( Object key ) {
        if ( logger.isTraceEnabled() ) {
            String msg = "get() - in thread [" + Thread.currentThread().getName() + "]";
            logger.trace( msg );
        }
        Object value = getResources().get( key );
        if ( ( value != null ) && logger.isTraceEnabled() ) {
            String msg = "Retrieved value of type [" + value.getClass().getName() + "] for key [" +
                key + "] " + "bound to thread [" + Thread.currentThread().getName() + "]";
            logger.trace( msg );
        }
        return value;
    }

    /**
     * Binds <tt>value</tt> for the given <code>key</code> to the current thread.
     *
     * <p>A <tt>null</tt> <tt>value</tt> has the same effect as if <tt>remove</tt> was called for the given
     * <tt>key</tt>, i.e.:
     *
     * <pre>
     * if ( value == null ) {
     *     remove( key );
     * }</pre>
     *
     * @param key   The key with which to identify the <code>value</code>.
     * @param value The value to bind to the thread.
     * @throws IllegalArgumentException if the <code>key</code> argument is <tt>null</tt>.
     */
    public static void put( Object key, Object value ) {
        if ( key == null ) {
            throw new IllegalArgumentException( "key cannot be null" );
        }

        if ( value == null ) {
            remove( key );
            return;
        }

        getResources().put( key, value );

        if ( logger.isTraceEnabled() ) {
            String msg = "Bound value of type [" + value.getClass().getName() + "] for key [" +
                key + "] to thread " + "[" + Thread.currentThread().getName() + "]";
            logger.trace( msg );
        }
    }

    /**
     * Unbinds the value for the given <code>key</code> from the current
     * thread.
     *
     * @param key The key identifying the value bound to the current thread.
     * @return the object unbound or <tt>null</tt> if there was nothing bound
     *         under the specified <tt>key</tt> name.
     */
    public static Object remove( Object key ) {
        Object value = getResources().remove( key );

        if ( ( value != null ) && logger.isTraceEnabled() ) {
            String msg = "Removed value of type [" + value.getClass().getName() + "] for key [" +
                key + "]" + "from thread [" + Thread.currentThread().getName() + "]";
            logger.trace( msg );
        }

        return value;
    }

    /**
     * Returns true if a value for the <code>key</code> is bound to the current thread, false otherwise.
     *
     * @param key the key that may identify a value bound to the current thread.
     * @return true if a value for the key is bound to the current thread, false
     *         otherwise.
     */
    public static boolean containsKey( Object key ) {
        return getResources().containsKey( key );
    }

    /**
     * Removes <em>all</em> values bound to this ThreadContext, which includes any Subject, Session, or InetAddress
     * that may be bound by these respective objects' conveninece methods, as well as all values bound by your
     * application code.
     * 
     * <p>This operation is meant as a clean-up operation that may be called at the end of
     * thread execution to prevent data corruption in a pooled thread environment.
     */
    public static void clear() {
        getResources().clear();
        if ( logger.isTraceEnabled() ) {
            logger.trace( "Removed all ThreadContext values from thread [" + Thread.currentThread().getName() + "]" );
        }
    }

    /**
     * Convenience method that simplifies retrieval of a thread-bound Subject.  If there is no
     * Subject bound to the thread, this method returns <tt>null</tt>.  It is merely a convenient wrapper
     * for the following:
     * <pre>
     * return (Subject)get( SECURITY_CONTEXT_KEY );</pre>
     *
     * <p>This method only returns the bound value if it exists - it does not remove it
     * from the thread.  To remove it, one must call {@link #unbindSubject() unbindSubject()} instead.
     *
     * @return the Subject object bound to the thread, or <tt>null</tt> if there isn't one bound.
     * @since 0.2
     */
    public static Subject getSubject() {
        return (Subject)get(SUBJECT_KEY);
    }


    /**
     * Convenience method that simplifies binding a Subject to the ThreadContext.
     *
     * <p>The method's existence is to help reduce casting in your own code and to simplify remembering of
     * ThreadContext key names.  The implementation is simple in that, if the Subject is not <tt>null</tt>,
     * it binds it to the thread, i.e.:
     *
     * <pre>
     * if (subject != null) {
     *     put( SECURITY_CONTEXT_KEY, subject );
     * }</pre>
     *
     * @param subject the Subject object to bind to the thread.  If the argument is null, nothing will be done.
     * @since 0.2
     */
    public static void bind( Subject subject) {
        if ( subject != null ) {
            put(SUBJECT_KEY, subject);
        }
    }

    /**
     * Convenience method that simplifies removal of a thread-local Subject from the thread.
     * 
     * <p>The implementation just helps reduce casting and remembering of the ThreadContext key name, i.e it is
     * merely a conveient wrapper for the following:
     *
     * <pre>
     * return (Subject)remove( SECURITY_CONTEXT_KEY );</pre>
     *
     * <p>If you wish to just retrieve the object from the thread without removing it (so it can be retrieved later during
     * thread execution), you should use the {@link #getSubject() getSubject()} method for that purpose.
     *
     * @return the Subject object previously bound to the thread, or <tt>null</tt> if there was none bound.
     * @since 0.2
     */
    public static Subject unbindSubject() {
        return (Subject)remove(SUBJECT_KEY);
    }

    /**
     * Convenience method that simplifies retrieval of a thread-bound InetAddress.  If there is no
     * InetAddress bound to the thread, this method returns <tt>null</tt>.  It is merely a convenient wrapper
     * for the following:
     * <pre>
     * return (InetAddress)get( INET_ADDRESS_KEY );</pre>
     *
     * <p>This method only returns the bound value if it exists - it does not remove it
     * from the thread.  To remove it, one must call {@link #unbindInetAddress() unbindInetAddress} instead.
     *
     * @return the InetAddress object bound to the thread, or <tt>null</tt> if there isn't one bound.
     * @since 0.2
     */
    public static InetAddress getInetAddress() {
        return (InetAddress)get( INET_ADDRESS_KEY );
    }

    /**
     * Convenience method that simplifies binding an InetAddress to the ThreadContext.
     *
     * <p>The method's existence is to help reduce casting in your own code and to simplify remembering of
     * ThreadContext key names.  The implementation is simple in that, if the inetAddress is not <tt>null</tt>,
     * it binds it to the thread, i.e.:
     *
     * <pre>
     * if (inetAddress != null) {
     *     put( INET_ADDRESS_KEY, inetAddress );
     * }</pre>
     *
     * @param inetAddress the InetAddress to bind to the thread.  If the argument is null, nothing will be done.
     * @since 0.2
     */
    public static void bind( InetAddress inetAddress ) {
        if ( inetAddress != null ) {
            put( INET_ADDRESS_KEY, inetAddress );
        }
    }

    /**
     * Convenience method that simplifies removal of a thread-local InetAddress from the thread.
     *
     * <p>The implementation just helps reduce casting and remembering of the ThreadContext key name, i.e it is
     * merely a conveient wrapper for the following:
     *
     * <pre>
     * return (InetAddress)remove( INET_ADDRESS_KEY );</pre>
     *
     * <p>If you wish to just retrieve the object from the thread without removing it (so it can be retrieved later during
     * thread execution), you should use the {@link #getInetAddress() getInetAddress()} method for that purpose.
     *
     * @return the InetAddress object previously bound to the thread, or <tt>null</tt> if there was none bound.
     * @since 0.2
     */
    public static InetAddress unbindInetAddress() {
        return (InetAddress)remove( INET_ADDRESS_KEY );
    }

    /**
     * Convenience method that simplifies retrieval of a thread-bound ServletRequest.  If there is no
     * ServletRequest bound to the thread, this method returns <tt>null</tt>.  It is merely a convenient wrapper
     * for the following:
     * <pre>
     * return (ServletRequest)get( SERVLET_REQUEST_KEY );</pre>
     *
     * <p>This method only returns the bound value if it exists - it does not remove it
     * from the thread.  To remove it, one must call {@link #unbindServletRequest() unbindServletRequest} instead.
     *
     * @return the ServletRequest bound to the thread, or <tt>null</tt> if there isn't one bound.
     * @since 0.2
     */
    public static ServletRequest getServletRequest() {
        return (ServletRequest)get( SERVLET_REQUEST_KEY );
    }

    /**
     * Convenience method that simplifies binding a ServletRequest to the ThreadContext.
     *
     * <p>The method's existence is to help reduce casting in your own code and to simplify remembering of
     * ThreadContext key names.  The implementation is simple in that, if the servletRequest is not <tt>null</tt>,
     * it binds it to the thread, i.e.:
     *
     * <pre>
     * if (servletRequest != null) {
     *     put( SERVLET_REQUEST_KEY, session );
     * }</pre>
     *
     * @param servletRequest the ServletRequest object to bind to the thread.  If the argument is null, nothing will be done.
     * @since 0.2
     */
    public static void bind( ServletRequest servletRequest ) {
        if ( servletRequest != null ) {
            put( SERVLET_REQUEST_KEY, servletRequest );
        }
    }

    /**
     * Convenience method that simplifies removal of a thread-local ServletRequest from the thread.
     *
     * <p>The implementation just helps reduce casting and remembering of the ThreadContext key name, i.e it is
     * merely a conveient wrapper for the following:
     *
     * <pre>
     * return (ServletRequest)remove( SERVLET_REQUEST_KEY );</pre>
     *
     * <p>If you wish to just retrieve the object from the thread without removing it (so it can be retrieved later during
     * thread execution), you should use the {@link #getServletRequest() getServletRequest()} method for that purpose.
     *
     * @return the Session object previously bound to the thread, or <tt>null</tt> if there was none bound.
     * @since 0.2
     */
    public static ServletRequest unbindServletRequest() {
        return (ServletRequest)remove( SERVLET_REQUEST_KEY );
    }

    /**
     * Convenience method that simplifies retrieval of a thread-bound ServletResponse.  If there is no
     * ServletResponse bound to the thread, this method returns <tt>null</tt>.  It is merely a convenient wrapper
     * for the following:
     * <pre>
     * return (ServletResponse)get( SERVLET_RESPONSE_KEY );</pre>
     *
     * <p>This method only returns the bound value if it exists - it does not remove it
     * from the thread.  To remove it, one must call {@link #unbindServletResponse() unbindServletResponse} instead.
     *
     * @return the ServletResponse bound to the thread, or <tt>null</tt> if there isn't one bound.
     * @since 0.2
     */
    public static ServletResponse getServletResponse() {
        return (ServletResponse)get( SERVLET_RESPONSE_KEY );
    }

    /**
     * Convenience method that simplifies binding a ServletResponse to the ThreadContext.
     *
     * <p>The method's existence is to help reduce casting in your own code and to simplify remembering of
     * ThreadContext key names.  The implementation is simple in that, if the servletResponse is not <tt>null</tt>,
     * it binds it to the thread, i.e.:
     *
     * <pre>
     * if (servletResponse != null) {
     *     put( SERVLET_RESPONSE_KEY, session );
     * }</pre>
     *
     * @param servletResponse the ServletResponse object to bind to the thread.  If the argument is null, nothing will be done.
     * @since 0.2
     */
    public static void bind( ServletResponse servletResponse ) {
        if ( servletResponse != null ) {
            put( SERVLET_RESPONSE_KEY, servletResponse );
        }
    }

    /**
     * Convenience method that simplifies removal of a thread-local ServletResponse from the thread.
     *
     * <p>The implementation just helps reduce casting and remembering of the ThreadContext key name, i.e it is
     * merely a conveient wrapper for the following:
     *
     * <pre>
     * return (ServletResponse)remove( SERVLET_RESPONSE_KEY );</pre>
     *
     * <p>If you wish to just retrieve the object from the thread without removing it (so it can be retrieved later during
     * thread execution), you should use the {@link #getServletResponse() getServletResponse()} method for that purpose.
     *
     * @return the Session object previously bound to the thread, or <tt>null</tt> if there was none bound.
     * @since 0.2
     */
    public static ServletResponse unbindServletResponse() {
        return (ServletResponse)remove( SERVLET_RESPONSE_KEY );
    }



}

