/*
 * 
 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * The contents of this file are subject to the Sun Community Source
 * License v3.0/Jini Technology Specific Attachment v 1.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://wwws.sun.com/software/jini/licensing/SCSL3_JiniTSA1.html.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Reference Code is Jini Technology Core Platform code, v2.0. The
 * Developer of the Reference Code is Sun Microsystems, Inc.
 * 
 * Contributor(s): Sun Microsystems, Inc.
 * 
 * The contents of this file comply with the Jini Technology Core
 * Platform Compatibility Kit, v2.0A.
 * 
 * Tester(s): Sun Microsystems, Inc.
 * 
 * Test Platform(s):
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Solaris(TM)SPARC/x86
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Linux (Intel x86)
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Windows (Intel Platform)
 * 
 */

package com.sun.jini.jeri.internal.http;

import com.sun.jini.thread.Executor;
import com.sun.jini.thread.GetThreadPoolAction;

/**
 * Utility class for timing out connections.
 *
 * @author Sun Microsystems, Inc.
 * 
 */
public class ConnectionTimer {
    
    private static final Executor systemThreadPool = (Executor)
	java.security.AccessController.doPrivileged(
	    new GetThreadPoolAction(false));

    private final TimeoutMap timeouts;

    /**
     * Creates new ConnectionTimer which shuts down overdue connections after
     * the given timeout.
     */
    public ConnectionTimer(long timeout) {
	timeouts = new TimeoutMap(timeout);
    }

    /**
     * Schedules timeout for given connection.  If timeout is already scheduled
     * for given connection, renews timeout.  When the timeout occurs, the
     * connection's shutdown method will be called with the given force value.
     */
    public void scheduleTimeout(TimedConnection conn, boolean force) {
	if (conn == null) {
	    throw new NullPointerException();
	}
	timeouts.put(conn, new Boolean(force));
    }

    /**
     * Attempts to cancel timeout for the given connection.  Returns true if a
     * timeout was successfully cancelled, false otherwise (e.g. if connection
     * was never scheduled for a timeout, has already been timed out, or is
     * already in the midst of being timed out).
     */
    public boolean cancelTimeout(TimedConnection conn) {
	if (conn == null) {
	    throw new NullPointerException();
	}
	return timeouts.remove(conn) != null;
    }

    /**
     * Map for tracking idle connection timeouts.
     */
    private static class TimeoutMap extends TimedMap {
	
	TimeoutMap(long timeout) {
	    super(systemThreadPool, timeout);
	}
	
	void evicted(Object key, Object value) {
	    boolean force = ((Boolean) value).booleanValue();
	    ((TimedConnection) key).shutdown(force);
	}
    }
}
