JDK14/Java14源码在线阅读

/*
 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5.internal.rcache;

import sun.security.krb5.internal.Krb5;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import sun.security.krb5.internal.KerberosTime;
import sun.security.krb5.internal.KrbApErrException;

/**
 * This class provides an efficient caching mechanism to store AuthTimeWithHash
 * from client authenticators. The cache minimizes the memory usage by doing
 * self-cleanup of expired items in the cache.
 *
 * AuthTimeWithHash objects inside a cache are always sorted from big (new) to
 * small (old) as determined by {@link AuthTimeWithHash#compareTo}. In the most
 * common case a newcomer should be newer than the first element.
 *
 * @author Yanni Zhang
 */
public class AuthList {

    private final LinkedList<AuthTimeWithHash> entries;
    private final int lifespan;

    // entries.getLast().ctime, updated after each cleanup.
    private volatile int oldestTime = Integer.MIN_VALUE;

    /**
     * Constructs a AuthList.
     */
    public AuthList(int lifespan) {
        this.lifespan = lifespan;
        entries = new LinkedList<>();
    }

    /**
     * Puts the authenticator timestamp into the cache in descending order,
     * and throw an exception if it's already there.
     */
    public synchronized void put(AuthTimeWithHash t, KerberosTime currentTime)
            throws KrbApErrException {

        if (entries.isEmpty()) {
            entries.addFirst(t);
            oldestTime = t.ctime;
            return;
        } else {
            AuthTimeWithHash temp = entries.getFirst();
            int cmp = temp.compareTo(t);
            if (cmp < 0) {
                // This is the most common case, newly received authenticator
                // has larger timestamp.
                entries.addFirst(t);
            } else if (cmp == 0) {
                throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
            } else {
                //unless client clock being re-adjusted.
                ListIterator<AuthTimeWithHash> it = entries.listIterator(1);
                boolean found = false;
                while (it.hasNext()) {
                    temp = it.next();
                    cmp = temp.compareTo(t);
                    if (cmp < 0) {
                        // Find an older one, put in front of it
                        entries.add(entries.indexOf(temp), t);
                        found = true;
                        break;
                    } else if (cmp == 0) {
                        throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
                    }
                }
                if (!found) {
                    // All is newer than the newcomer. Sigh.
                    entries.addLast(t);
                }
            }
        }

        // let us cleanup while we are here
        long timeLimit = currentTime.getSeconds() - lifespan;

        // Only trigger a cleanup when the earliest entry is
        // lifespan + 5 sec ago. This ensures a cleanup is done
        // at most every 5 seconds so that we don't always
        // addLast(removeLast).
        if (oldestTime > timeLimit - 5) {
            return;
        }

        // and we remove the *enough* old ones (1 lifetime ago)
        while (!entries.isEmpty()) {
            AuthTimeWithHash removed = entries.removeLast();
            if (removed.ctime >= timeLimit) {
                entries.addLast(removed);
                oldestTime = removed.ctime;
                return;
            }
        }


/**代码未完, 请加载全部代码(NowJava.com).**/
展开阅读全文

关注时代Java

关注时代Java