/*
 * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.security.pkcs11;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import java.security.*;

import sun.security.pkcs11.wrapper.*;

/**
 * A session object. Sessions are obtained via the SessionManager,
 * see there for details. Most code will only ever need one method in
 * this class, the id() method to obtain the session id.
 *
 * @author  Andreas Sterbenz
 * @since   1.5
 */
final class Session implements Comparable<Session> {

    // time after which to close idle sessions, in milliseconds (3 minutes)
    private final static long MAX_IDLE_TIME = 3 * 60 * 1000;

    // token instance
    final Token token;

    // session id
    private final long id;

    // number of objects created within this session
    private final AtomicInteger createdObjects;

    // time this session was last used
    // not synchronized/volatile for performance, so may be unreliable
    // this could lead to idle sessions being closed early, but that is harmless
    private long lastAccess;

    Session(Token token, long id) {
        this.token = token;
        this.id = id;
        createdObjects = new AtomicInteger();
        id();
    }

    public int compareTo(Session other) {
        if (this.lastAccess == other.lastAccess) {
            return 0;
        } else {
            return (this.lastAccess < other.lastAccess) ? -1 : 1;
        }
    }

    boolean isLive(long currentTime) {
        return currentTime - lastAccess < MAX_IDLE_TIME;
    }

    long idInternal() {
        return id;
    }

    long id() {
        if (token.isPresent(this) == false) {
            throw new ProviderException("Token has been removed");
        }
        lastAccess = System.currentTimeMillis();
        return id;
    }

    void addObject() {
        int n = createdObjects.incrementAndGet();
        // XXX update statistics in session manager if n == 1
    }

    void removeObject() {
        int n = createdObjects.decrementAndGet();
        if (n == 0) {
            token.sessionManager.demoteObjSession(this);
        } else if (n < 0) {
            throw new ProviderException("Internal error: objects created " + n);
        }
    }

    boolean hasObjects() {
        return createdObjects.get() != 0;
    }

}
