--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,257 @@
+/*
+ * Copyright 1999-2007 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.ssl;
+
+import java.io.*;
+import java.net.*;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+
+import sun.misc.Cache;
+
+
+final class SSLSessionContextImpl implements SSLSessionContext
+{
+ private Cache sessionCache = new Cache();
+ private Cache sessionHostPortCache = new Cache();
+ private int cacheLimit;
+ private long timeoutMillis;
+ private static final Debug debug = Debug.getInstance("ssl");
+
+ // file private
+ SSLSessionContextImpl()
+ {
+ cacheLimit = getCacheLimit();
+ timeoutMillis = 86400000; // default, 24 hours
+ }
+
+ /**
+ * Returns the SSL session object associated with the
+ * specific session ID passed.
+ */
+ public SSLSession getSession(byte[] id)
+ {
+ SSLSession sess = (SSLSession) sessionCache.get(
+ new SessionId(id));
+ return checkTimeValidity(sess);
+ }
+
+ /**
+ * Returns an enumeration of the active SSL sessions.
+ */
+ public Enumeration<byte[]> getIds() {
+ Vector<byte[]> v = new Vector<byte[]>(sessionCache.size());
+ SessionId sessId;
+
+ for (Enumeration e = sessionCache.keys(); e.hasMoreElements(); ) {
+ sessId = (SessionId) e.nextElement();
+ if (!isTimedout((SSLSession)sessionCache.get(sessId)))
+ v.addElement(sessId.getId());
+ }
+ return v.elements();
+ }
+
+ public void setSessionTimeout(int seconds)
+ throws IllegalArgumentException {
+ if (seconds < 0)
+ throw new IllegalArgumentException();
+ timeoutMillis = seconds * 1000L;
+ }
+
+ public int getSessionTimeout() {
+ return (int) (timeoutMillis / 1000);
+ }
+
+ public void setSessionCacheSize(int size)
+ throws IllegalArgumentException {
+ if (size < 0)
+ throw new IllegalArgumentException();
+ cacheLimit = size;
+
+ /**
+ * If cache size limit is reduced, when the cache is full to its
+ * previous limit, trim the cache before its contents
+ * are used.
+ */
+ if ((cacheLimit != 0) && (sessionCache.size() > cacheLimit))
+ adjustCacheSizeTo(cacheLimit);
+ }
+
+ public int getSessionCacheSize() {
+ return cacheLimit;
+ }
+
+ SSLSessionImpl get(byte[] id) {
+ return (SSLSessionImpl) getSession(id);
+ }
+
+ /**
+ * Returns the SSL session object associated with the
+ * specific host name and port number passed.
+ */
+ SSLSessionImpl get(String hostname, int port) {
+ /*
+ * If no session caching info is available, we won't
+ * get one, so exit before doing a lookup.
+ */
+ if (hostname == null && port == -1) {
+ return null;
+ }
+ SSLSession sess = (SSLSessionImpl) sessionHostPortCache
+ .get(getKey(hostname, port));
+ return (SSLSessionImpl) checkTimeValidity(sess);
+ }
+
+ private String getKey(String hostname, int port) {
+ return (hostname + ":" + String.valueOf(port))
+ .toLowerCase();
+ }
+
+ void put(SSLSessionImpl s) {
+ // make space for the new session to be added
+ if ((cacheLimit != 0) && (sessionCache.size() >= cacheLimit))
+ adjustCacheSizeTo(cacheLimit - 1);
+
+ /*
+ * Can always add the session id.
+ */
+ sessionCache.put(s.getSessionId(), s);
+
+ /*
+ * If no hostname/port info is available, don't add this one.
+ */
+ if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) {
+ sessionHostPortCache.put(
+ getKey(s.getPeerHost(), s.getPeerPort()), s);
+ }
+ s.setContext(this);
+ }
+
+ private void adjustCacheSizeTo(int targetSize) {
+
+ int cacheSize = sessionCache.size();
+
+ if (targetSize < 0)
+ return;
+
+ while (cacheSize > targetSize) {
+ SSLSessionImpl lru = null;
+ SSLSessionImpl s = null;
+ Enumeration e;
+
+ if (debug != null && Debug.isOn("sessioncache")) {
+ System.out.println("exceeded cache limit of " + cacheLimit);
+ }
+
+ /*
+ * Count the number of elements in the cache. The size() method
+ * does not reflect the cache entries that are no longer available,
+ * i.e entries that are garbage collected (the cache entries are
+ * held using soft references and are garbage collected when not
+ * in use).
+ */
+ int count;
+ for (count = 0, e = sessionCache.elements();
+ e.hasMoreElements(); count++) {
+ try {
+ s = (SSLSessionImpl)e.nextElement();
+ } catch (NoSuchElementException nsee) {
+ break;
+ }
+ if (isTimedout(s)) {
+ lru = s;
+ break;
+ } else if ((lru == null) || (s.getLastAccessedTime()
+ < lru.getLastAccessedTime())) {
+ lru = s;
+ }
+ }
+ if ((lru != null) && (count > targetSize)) {
+ if (debug != null && Debug.isOn("sessioncache")) {
+ System.out.println("uncaching " + lru);
+ }
+ lru.invalidate();
+ count--; // element removed from the cache
+ }
+ cacheSize = count;
+ }
+ }
+
+ // file private
+ void remove(SessionId key)
+ {
+ SSLSessionImpl s = (SSLSessionImpl) sessionCache.get(key);
+ sessionCache.remove(key);
+ sessionHostPortCache.remove(getKey(s.getPeerHost(),
+ s.getPeerPort()));
+ }
+
+ private int getCacheLimit() {
+ int cacheLimit = 0;
+ try {
+ String s = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(
+ "javax.net.ssl.sessionCacheSize");
+ }
+ });
+ cacheLimit = (s != null) ? Integer.valueOf(s).intValue() : 0;
+ } catch (Exception e) {
+ }
+
+ return (cacheLimit > 0) ? cacheLimit : 0;
+ }
+
+ SSLSession checkTimeValidity(SSLSession sess) {
+ if (isTimedout(sess)) {
+ sess.invalidate();
+ return null;
+ } else
+ return sess;
+ }
+
+ boolean isTimedout(SSLSession sess) {
+ if (timeoutMillis == 0)
+ return false;
+ if ((sess != null) &&
+ ((sess.getCreationTime() + timeoutMillis)
+ <= (System.currentTimeMillis())))
+ return true;
+ return false;
+ }
+}