# HG changeset patch # User mullan # Date 1319033782 14400 # Node ID 34cd7a6c34683e20ffde7d417940d2c821d4d7c9 # Parent 680a3dbfcaba69cf008702f03a07afd76b499ac7# Parent 717ef54d7dd32952b3fc43009a9d3bf0274e048a Merge diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/pkcs11/KeyCache.java --- a/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java Wed Oct 19 10:16:22 2011 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -48,7 +48,7 @@ */ final class KeyCache { - private final Cache strongCache; + private final Cache strongCache; private WeakReference> cacheReference; @@ -77,7 +77,7 @@ } synchronized P11Key get(Key key) { - P11Key p11Key = (P11Key)strongCache.get(new IdentityWrapper(key)); + P11Key p11Key = strongCache.get(new IdentityWrapper(key)); if (p11Key != null) { return p11Key; } @@ -94,8 +94,8 @@ Map map = (cacheReference == null) ? null : cacheReference.get(); if (map == null) { - map = new IdentityHashMap(); - cacheReference = new WeakReference>(map); + map = new IdentityHashMap<>(); + cacheReference = new WeakReference<>(map); } map.put(key, p11Key); } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/provider/X509Factory.java --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java Wed Oct 19 10:16:22 2011 -0400 @@ -64,8 +64,10 @@ private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX - private static final Cache certCache = Cache.newSoftMemoryCache(750); - private static final Cache crlCache = Cache.newSoftMemoryCache(750); + private static final Cache certCache + = Cache.newSoftMemoryCache(750); + private static final Cache crlCache + = Cache.newSoftMemoryCache(750); /** * Generates an X.509 certificate object and initializes it with @@ -90,7 +92,7 @@ try { byte[] encoding = readOneBlock(is); if (encoding != null) { - X509CertImpl cert = (X509CertImpl)getFromCache(certCache, encoding); + X509CertImpl cert = getFromCache(certCache, encoding); if (cert != null) { return cert; } @@ -151,7 +153,7 @@ } else { encoding = c.getEncoded(); } - X509CertImpl newC = (X509CertImpl)getFromCache(certCache, encoding); + X509CertImpl newC = getFromCache(certCache, encoding); if (newC != null) { return newC; } @@ -181,7 +183,7 @@ } else { encoding = c.getEncoded(); } - X509CRLImpl newC = (X509CRLImpl)getFromCache(crlCache, encoding); + X509CRLImpl newC = getFromCache(crlCache, encoding); if (newC != null) { return newC; } @@ -198,18 +200,17 @@ /** * Get the X509CertImpl or X509CRLImpl from the cache. */ - private static synchronized Object getFromCache(Cache cache, + private static synchronized V getFromCache(Cache cache, byte[] encoding) { Object key = new Cache.EqualByteArray(encoding); - Object value = cache.get(key); - return value; + return cache.get(key); } /** * Add the X509CertImpl or X509CRLImpl to the cache. */ - private static synchronized void addToCache(Cache cache, byte[] encoding, - Object value) { + private static synchronized void addToCache(Cache cache, + byte[] encoding, V value) { if (encoding.length > ENC_MAX_LENGTH) { return; } @@ -361,7 +362,7 @@ try { byte[] encoding = readOneBlock(is); if (encoding != null) { - X509CRLImpl crl = (X509CRLImpl)getFromCache(crlCache, encoding); + X509CRLImpl crl = getFromCache(crlCache, encoding); if (crl != null) { return crl; } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java --- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Wed Oct 19 10:16:22 2011 -0400 @@ -59,12 +59,13 @@ "SSLServer", "sun.security.provider.certpath.ssl.SSLServerCertStoreHelper"); }; - private static Cache cache = Cache.newSoftMemoryCache(NUM_TYPES); + private static Cache cache + = Cache.newSoftMemoryCache(NUM_TYPES); public static CertStoreHelper getInstance(final String type) throws NoSuchAlgorithmException { - CertStoreHelper helper = (CertStoreHelper)cache.get(type); + CertStoreHelper helper = cache.get(type); if (helper != null) { return helper; } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed Oct 19 10:16:22 2011 -0400 @@ -100,8 +100,7 @@ private final CertificateFactory factory; // cached Collection of X509Certificates (may be empty, never null) - private Collection certs = - Collections.emptySet(); + private Collection certs = Collections.emptySet(); // cached X509CRL (may be null) private X509CRL crl; @@ -157,14 +156,14 @@ * Returns a URI CertStore. This method consults a cache of * CertStores (shared per JVM) using the URI as a key. */ - private static final Cache certStoreCache = - Cache.newSoftMemoryCache(CACHE_SIZE); + private static final Cache + certStoreCache = Cache.newSoftMemoryCache(CACHE_SIZE); static synchronized CertStore getInstance(URICertStoreParameters params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { if (debug != null) { debug.println("CertStore URI:" + params.uri); } - CertStore ucs = (CertStore) certStoreCache.get(params); + CertStore ucs = certStoreCache.get(params); if (ucs == null) { ucs = new UCS(new URICertStore(params), null, "URI", params); certStoreCache.put(params, ucs); @@ -287,7 +286,7 @@ } // exception, forget previous values lastModified = 0; - certs = Collections.emptySet(); + certs = Collections.emptySet(); return certs; } @@ -394,7 +393,7 @@ // exception, forget previous values lastModified = 0; crl = null; - return Collections.emptyList(); + return Collections.emptyList(); } /** @@ -404,9 +403,9 @@ private static Collection getMatchingCRLs (X509CRL crl, CRLSelector selector) { if (selector == null || (crl != null && selector.match(crl))) { - return Collections.singletonList(crl); + return Collections.singletonList(crl); } else { - return Collections.emptyList(); + return Collections.emptyList(); } } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java --- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Wed Oct 19 10:16:22 2011 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -79,7 +79,8 @@ private X509Certificate reverse; private byte[] encoded; - private static final Cache cache = Cache.newSoftMemoryCache(750); + private static final Cache cache + = Cache.newSoftMemoryCache(750); /** * Creates an empty instance of X509CertificatePair. @@ -114,7 +115,7 @@ * * For internal use only, external code should use generateCertificatePair. */ - private X509CertificatePair(byte[] encoded)throws CertificateException { + private X509CertificatePair(byte[] encoded) throws CertificateException { try { parse(new DerValue(encoded)); this.encoded = encoded; @@ -138,7 +139,7 @@ public static synchronized X509CertificatePair generateCertificatePair (byte[] encoded) throws CertificateException { Object key = new Cache.EqualByteArray(encoded); - X509CertificatePair pair = (X509CertificatePair)cache.get(key); + X509CertificatePair pair = cache.get(key); if (pair != null) { return pair; } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java Wed Oct 19 10:16:22 2011 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -160,7 +160,7 @@ */ private boolean prefetchCRLs = false; - private final Cache valueCache; + private final Cache valueCache; private int cacheHits = 0; private int cacheMisses = 0; @@ -207,10 +207,11 @@ * Returns an LDAP CertStore. This method consults a cache of * CertStores (shared per JVM) using the LDAP server/port as a key. */ - private static final Cache certStoreCache = Cache.newSoftMemoryCache(185); + private static final Cache + certStoreCache = Cache.newSoftMemoryCache(185); static synchronized CertStore getInstance(LDAPCertStoreParameters params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { - CertStore lcs = (CertStore) certStoreCache.get(params); + CertStore lcs = certStoreCache.get(params); if (lcs == null) { lcs = CertStore.getInstance("LDAP", params); certStoreCache.put(params, lcs); @@ -232,7 +233,7 @@ private void createInitialDirContext(String server, int port) throws InvalidAlgorithmParameterException { String url = "ldap://" + server + ":" + port; - Hashtable env = new Hashtable(); + Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); @@ -283,7 +284,7 @@ LDAPRequest(String name) { this.name = name; - requestedAttributes = new ArrayList(5); + requestedAttributes = new ArrayList<>(5); } String getName() { @@ -311,7 +312,7 @@ + cacheMisses); } String cacheKey = name + "|" + attrId; - byte[][] values = (byte[][])valueCache.get(cacheKey); + byte[][] values = valueCache.get(cacheKey); if (values != null) { cacheHits++; return values; @@ -347,7 +348,7 @@ System.out.println("LDAP requests: " + requests); } } - valueMap = new HashMap(8); + valueMap = new HashMap<>(8); String[] attrIds = requestedAttributes.toArray(STRING0); Attributes attrs; try { @@ -429,10 +430,10 @@ int n = encodedCert.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List certs = new ArrayList(n); + List certs = new ArrayList<>(n); /* decode certs and check if they satisfy selector */ for (int i = 0; i < n; i++) { ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]); @@ -477,11 +478,10 @@ int n = encodedCertPair.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List certPairs = - new ArrayList(n); + List certPairs = new ArrayList<>(n); /* decode each cert pair and add it to the Collection */ for (int i = 0; i < n; i++) { try { @@ -528,8 +528,7 @@ getCertPairs(request, CROSS_CERT); // Find Certificates that match and put them in a list - ArrayList matchingCerts = - new ArrayList(); + ArrayList matchingCerts = new ArrayList<>(); for (X509CertificatePair certPair : certPairs) { X509Certificate cert; if (forward != null) { @@ -587,7 +586,7 @@ int basicConstraints = xsel.getBasicConstraints(); String subject = xsel.getSubjectAsString(); String issuer = xsel.getIssuerAsString(); - HashSet certs = new HashSet(); + HashSet certs = new HashSet<>(); if (debug != null) { debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: " + basicConstraints); @@ -706,10 +705,10 @@ int n = encodedCRL.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List crls = new ArrayList(n); + List crls = new ArrayList<>(n); /* decode each crl and check if it matches selector */ for (int i = 0; i < n; i++) { try { @@ -765,13 +764,13 @@ throw new CertStoreException("need X509CRLSelector to find CRLs"); } X509CRLSelector xsel = (X509CRLSelector) selector; - HashSet crls = new HashSet(); + HashSet crls = new HashSet<>(); // Look in directory entry for issuer of cert we're checking. Collection issuerNames; X509Certificate certChecking = xsel.getCertificateChecking(); if (certChecking != null) { - issuerNames = new HashSet(); + issuerNames = new HashSet<>(); X500Principal issuer = certChecking.getIssuerX500Principal(); issuerNames.add(issuer.getName(X500Principal.RFC2253)); } else { @@ -796,7 +795,7 @@ issuerName = (String)nameObject; } // If all we want is CA certs, try to get the (probably shorter) ARL - Collection entryCRLs = Collections.emptySet(); + Collection entryCRLs = Collections.emptySet(); if (certChecking == null || certChecking.getBasicConstraints() != -1) { LDAPRequest request = new LDAPRequest(issuerName); request.addRequestedAttribute(CROSS_CERT); @@ -1028,9 +1027,9 @@ throws IOException { this.selector = selector == null ? new X509CRLSelector() : selector; this.certIssuers = certIssuers; - issuerNames = new HashSet(); + issuerNames = new HashSet<>(); issuerNames.add(ldapDN); - issuers = new HashSet(); + issuers = new HashSet<>(); issuers.add(new X500Name(ldapDN).asX500Principal()); } // we only override the get (accessor methods) since the set methods diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/ssl/CipherBox.java --- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java Wed Oct 19 10:16:22 2011 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, 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 @@ -305,9 +305,11 @@ byte[] buf = null; int limit = bb.limit(); if (bb.hasArray()) { + int arrayOffset = bb.arrayOffset(); buf = bb.array(); - System.arraycopy(buf, pos, - buf, pos + prefix.length, limit - pos); + System.arraycopy(buf, arrayOffset + pos, + buf, arrayOffset + pos + prefix.length, + limit - pos); bb.limit(limit + prefix.length); } else { buf = new byte[limit - pos]; @@ -491,9 +493,10 @@ byte[] buf = null; int limit = bb.limit(); if (bb.hasArray()) { + int arrayOffset = bb.arrayOffset(); buf = bb.array(); - System.arraycopy(buf, pos + blockSize, - buf, pos, limit - pos - blockSize); + System.arraycopy(buf, arrayOffset + pos + blockSize, + buf, arrayOffset + pos, limit - pos - blockSize); bb.limit(limit - blockSize); } else { buf = new byte[limit - pos - blockSize]; diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java --- a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java Wed Oct 19 10:16:22 2011 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -43,11 +43,14 @@ import javax.net.ssl.SSLSession; import sun.security.util.Cache; +import sun.security.util.Cache.CacheVisitor; final class SSLSessionContextImpl implements SSLSessionContext { - private Cache sessionCache; // session cache, session id as key - private Cache sessionHostPortCache; // session cache, "host:port" as key + private Cache sessionCache; + // session cache, session id as key + private Cache sessionHostPortCache; + // session cache, "host:port" as key private int cacheLimit; // the max cache size private int timeout; // timeout in seconds @@ -71,8 +74,7 @@ throw new NullPointerException("session id cannot be null"); } - SSLSessionImpl sess = - (SSLSessionImpl)sessionCache.get(new SessionId(sessionId)); + SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId)); if (!isTimedout(sess)) { return sess; } @@ -157,8 +159,7 @@ return null; } - SSLSessionImpl sess = - (SSLSessionImpl)sessionHostPortCache.get(getKey(hostname, port)); + SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port)); if (!isTimedout(sess)) { return sess; } @@ -193,7 +194,7 @@ // package-private method, remove a cached SSLSession void remove(SessionId key) { - SSLSessionImpl s = (SSLSessionImpl)sessionCache.get(key); + SSLSessionImpl s = sessionCache.get(key); if (s != null) { sessionCache.remove(key); sessionHostPortCache.remove( @@ -233,17 +234,17 @@ } final class SessionCacheVisitor - implements sun.security.util.Cache.CacheVisitor { + implements Cache.CacheVisitor { Vector ids = null; - // public void visit(java.util.Map map) {} - public void visit(java.util.Map map) { - ids = new Vector(map.size()); + // public void visit(java.util.Map map) {} + public void visit(java.util.Map map) { + ids = new Vector<>(map.size()); - for (Object key : map.keySet()) { - SSLSessionImpl value = (SSLSessionImpl)map.get(key); + for (SessionId key : map.keySet()) { + SSLSessionImpl value = map.get(key); if (!isTimedout(value)) { - ids.addElement(((SessionId)key).getId()); + ids.addElement(key.getId()); } } } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/src/share/classes/sun/security/util/Cache.java --- a/jdk/src/share/classes/sun/security/util/Cache.java Wed Oct 19 10:15:23 2011 -0400 +++ b/jdk/src/share/classes/sun/security/util/Cache.java Wed Oct 19 10:16:22 2011 -0400 @@ -43,7 +43,7 @@ * * . optional lifetime, specified in seconds. * - * . save for concurrent use by multiple threads + * . safe for concurrent use by multiple threads * * . values are held by either standard references or via SoftReferences. * SoftReferences have the advantage that they are automatically cleared @@ -69,7 +69,7 @@ * * @author Andreas Sterbenz */ -public abstract class Cache { +public abstract class Cache { protected Cache() { // empty @@ -88,12 +88,12 @@ /** * Add an entry to the cache. */ - public abstract void put(Object key, Object value); + public abstract void put(K key, V value); /** * Get a value from the cache. */ - public abstract Object get(Object key); + public abstract V get(Object key); /** * Remove an entry from the cache. @@ -113,14 +113,14 @@ /** * accept a visitor */ - public abstract void accept(CacheVisitor visitor); + public abstract void accept(CacheVisitor visitor); /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by SoftReferences. */ - public static Cache newSoftMemoryCache(int size) { - return new MemoryCache(true, size); + public static Cache newSoftMemoryCache(int size) { + return new MemoryCache<>(true, size); } /** @@ -128,23 +128,24 @@ * specified maximum lifetime (in seconds), with the values held * by SoftReferences. */ - public static Cache newSoftMemoryCache(int size, int timeout) { - return new MemoryCache(true, size, timeout); + public static Cache newSoftMemoryCache(int size, int timeout) { + return new MemoryCache<>(true, size, timeout); } /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by standard references. */ - public static Cache newHardMemoryCache(int size) { - return new MemoryCache(false, size); + public static Cache newHardMemoryCache(int size) { + return new MemoryCache<>(false, size); } /** * Return a dummy cache that does nothing. */ - public static Cache newNullCache() { - return NullCache.INSTANCE; + @SuppressWarnings("unchecked") + public static Cache newNullCache() { + return (Cache) NullCache.INSTANCE; } /** @@ -152,8 +153,8 @@ * specified maximum lifetime (in seconds), with the values held * by standard references. */ - public static Cache newHardMemoryCache(int size, int timeout) { - return new MemoryCache(false, size, timeout); + public static Cache newHardMemoryCache(int size, int timeout) { + return new MemoryCache<>(false, size, timeout); } /** @@ -193,15 +194,15 @@ } } - public interface CacheVisitor { - public void visit(Map map); + public interface CacheVisitor { + public void visit(Map map); } } -class NullCache extends Cache { +class NullCache extends Cache { - final static Cache INSTANCE = new NullCache(); + final static Cache INSTANCE = new NullCache<>(); private NullCache() { // empty @@ -215,11 +216,11 @@ // empty } - public void put(Object key, Object value) { + public void put(K key, V value) { // empty } - public Object get(Object key) { + public V get(Object key) { return null; } @@ -235,23 +236,26 @@ // empty } - public void accept(CacheVisitor visitor) { + public void accept(CacheVisitor visitor) { // empty } } -class MemoryCache extends Cache { +class MemoryCache extends Cache { private final static float LOAD_FACTOR = 0.75f; // XXXX private final static boolean DEBUG = false; - private final Map cacheMap; + private final Map> cacheMap; private int maxSize; private long lifetime; - private final ReferenceQueue queue; + + // ReferenceQueue is of type V instead of Cache + // to allow SoftCacheEntry to extend SoftReference + private final ReferenceQueue queue; public MemoryCache(boolean soft, int maxSize) { this(soft, maxSize, 0); @@ -260,10 +264,13 @@ public MemoryCache(boolean soft, int maxSize, int lifetime) { this.maxSize = maxSize; this.lifetime = lifetime * 1000; - this.queue = soft ? new ReferenceQueue() : null; + if (soft) + this.queue = new ReferenceQueue<>(); + else + this.queue = null; + int buckets = (int)(maxSize / LOAD_FACTOR) + 1; - cacheMap = new LinkedHashMap(buckets, - LOAD_FACTOR, true); + cacheMap = new LinkedHashMap<>(buckets, LOAD_FACTOR, true); } /** @@ -279,16 +286,17 @@ } int startSize = cacheMap.size(); while (true) { - CacheEntry entry = (CacheEntry)queue.poll(); + @SuppressWarnings("unchecked") + CacheEntry entry = (CacheEntry)queue.poll(); if (entry == null) { break; } - Object key = entry.getKey(); + K key = entry.getKey(); if (key == null) { // key is null, entry has already been removed continue; } - CacheEntry currentEntry = cacheMap.remove(key); + CacheEntry currentEntry = cacheMap.remove(key); // check if the entry in the map corresponds to the expired // entry. If not, readd the entry if ((currentEntry != null) && (entry != currentEntry)) { @@ -314,9 +322,9 @@ } int cnt = 0; long time = System.currentTimeMillis(); - for (Iterator t = cacheMap.values().iterator(); + for (Iterator> t = cacheMap.values().iterator(); t.hasNext(); ) { - CacheEntry entry = t.next(); + CacheEntry entry = t.next(); if (entry.isValid(time) == false) { t.remove(); cnt++; @@ -339,7 +347,7 @@ if (queue != null) { // if this is a SoftReference cache, first invalidate() all // entries so that GC does not have to enqueue them - for (CacheEntry entry : cacheMap.values()) { + for (CacheEntry entry : cacheMap.values()) { entry.invalidate(); } while (queue.poll() != null) { @@ -349,12 +357,12 @@ cacheMap.clear(); } - public synchronized void put(Object key, Object value) { + public synchronized void put(K key, V value) { emptyQueue(); long expirationTime = (lifetime == 0) ? 0 : System.currentTimeMillis() + lifetime; - CacheEntry newEntry = newEntry(key, value, expirationTime, queue); - CacheEntry oldEntry = cacheMap.put(key, newEntry); + CacheEntry newEntry = newEntry(key, value, expirationTime, queue); + CacheEntry oldEntry = cacheMap.put(key, newEntry); if (oldEntry != null) { oldEntry.invalidate(); return; @@ -362,8 +370,8 @@ if (maxSize > 0 && cacheMap.size() > maxSize) { expungeExpiredEntries(); if (cacheMap.size() > maxSize) { // still too large? - Iterator t = cacheMap.values().iterator(); - CacheEntry lruEntry = t.next(); + Iterator> t = cacheMap.values().iterator(); + CacheEntry lruEntry = t.next(); if (DEBUG) { System.out.println("** Overflow removal " + lruEntry.getKey() + " | " + lruEntry.getValue()); @@ -374,9 +382,9 @@ } } - public synchronized Object get(Object key) { + public synchronized V get(Object key) { emptyQueue(); - CacheEntry entry = cacheMap.get(key); + CacheEntry entry = cacheMap.get(key); if (entry == null) { return null; } @@ -393,7 +401,7 @@ public synchronized void remove(Object key) { emptyQueue(); - CacheEntry entry = cacheMap.remove(key); + CacheEntry entry = cacheMap.remove(key); if (entry != null) { entry.invalidate(); } @@ -402,9 +410,9 @@ public synchronized void setCapacity(int size) { expungeExpiredEntries(); if (size > 0 && cacheMap.size() > size) { - Iterator t = cacheMap.values().iterator(); + Iterator> t = cacheMap.values().iterator(); for (int i = cacheMap.size() - size; i > 0; i--) { - CacheEntry lruEntry = t.next(); + CacheEntry lruEntry = t.next(); if (DEBUG) { System.out.println("** capacity reset removal " + lruEntry.getKey() + " | " + lruEntry.getValue()); @@ -431,60 +439,61 @@ } // it is a heavyweight method. - public synchronized void accept(CacheVisitor visitor) { + public synchronized void accept(CacheVisitor visitor) { expungeExpiredEntries(); - Map cached = getCachedEntries(); + Map cached = getCachedEntries(); visitor.visit(cached); } - private Map getCachedEntries() { - Map kvmap = new HashMap(cacheMap.size()); + private Map getCachedEntries() { + Map kvmap = new HashMap<>(cacheMap.size()); - for (CacheEntry entry : cacheMap.values()) { + for (CacheEntry entry : cacheMap.values()) { kvmap.put(entry.getKey(), entry.getValue()); } return kvmap; } - protected CacheEntry newEntry(Object key, Object value, - long expirationTime, ReferenceQueue queue) { + protected CacheEntry newEntry(K key, V value, + long expirationTime, ReferenceQueue queue) { if (queue != null) { - return new SoftCacheEntry(key, value, expirationTime, queue); + return new SoftCacheEntry<>(key, value, expirationTime, queue); } else { - return new HardCacheEntry(key, value, expirationTime); + return new HardCacheEntry<>(key, value, expirationTime); } } - private static interface CacheEntry { + private static interface CacheEntry { boolean isValid(long currentTime); void invalidate(); - Object getKey(); + K getKey(); - Object getValue(); + V getValue(); } - private static class HardCacheEntry implements CacheEntry { + private static class HardCacheEntry implements CacheEntry { - private Object key, value; + private K key; + private V value; private long expirationTime; - HardCacheEntry(Object key, Object value, long expirationTime) { + HardCacheEntry(K key, V value, long expirationTime) { this.key = key; this.value = value; this.expirationTime = expirationTime; } - public Object getKey() { + public K getKey() { return key; } - public Object getValue() { + public V getValue() { return value; } @@ -503,24 +512,25 @@ } } - private static class SoftCacheEntry - extends SoftReference implements CacheEntry { + private static class SoftCacheEntry + extends SoftReference + implements CacheEntry { - private Object key; + private K key; private long expirationTime; - SoftCacheEntry(Object key, Object value, long expirationTime, - ReferenceQueue queue) { + SoftCacheEntry(K key, V value, long expirationTime, + ReferenceQueue queue) { super(value, queue); this.key = key; this.expirationTime = expirationTime; } - public Object getKey() { + public K getKey() { return key; } - public Object getValue() { + public V getValue() { return get(); } diff -r 680a3dbfcaba -r 34cd7a6c3468 jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Wed Oct 19 10:16:22 2011 -0400 @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2011, 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. + * + * 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. + */ + +/* + * @test + * @bug 7031830 + * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine + * @run main/othervm SSLEngineBadBufferArrayAccess + * + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + */ + +/** + * A SSLSocket/SSLEngine interop test case. This is not the way to + * code SSLEngine-based servers, but works for what we need to do here, + * which is to make sure that SSLEngine/SSLSockets can talk to each other. + * SSLEngines can use direct or indirect buffers, and different code + * is used to get at the buffer contents internally, so we test that here. + * + * The test creates one SSLSocket (client) and one SSLEngine (server). + * The SSLSocket talks to a raw ServerSocket, and the server code + * does the translation between byte [] and ByteBuffers that the SSLEngine + * can use. The "transport" layer consists of a Socket Input/OutputStream + * and two byte buffers for the SSLEngines: think of them + * as directly connected pipes. + * + * Again, this is a *very* simple example: real code will be much more + * involved. For example, different threading and I/O models could be + * used, transport mechanisms could close unexpectedly, and so on. + * + * When this application runs, notice that several messages + * (wrap/unwrap) pass before any application data is consumed or + * produced. (For more information, please see the SSL/TLS + * specifications.) There may several steps for a successful handshake, + * so it's typical to see the following series of operations: + * + * client server message + * ====== ====== ======= + * write() ... ClientHello + * ... unwrap() ClientHello + * ... wrap() ServerHello/Certificate + * read() ... ServerHello/Certificate + * write() ... ClientKeyExchange + * write() ... ChangeCipherSpec + * write() ... Finished + * ... unwrap() ClientKeyExchange + * ... unwrap() ChangeCipherSpec + * ... unwrap() Finished + * ... wrap() ChangeCipherSpec + * ... wrap() Finished + * read() ... ChangeCipherSpec + * read() ... Finished + * + * This particular bug had a problem where byte buffers backed by an + * array didn't offset correctly, and we got bad MAC errors. + */ +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.net.*; +import java.security.*; +import java.nio.*; + +public class SSLEngineBadBufferArrayAccess { + + /* + * Enables logging of the SSL/TLS operations. + */ + private static boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static boolean debug = false; + private SSLContext sslc; + private SSLEngine serverEngine; // server-side SSLEngine + private SSLSocket sslSocket; // client-side socket + private ServerSocket serverSocket; // server-side Socket, generates the... + private Socket socket; // server-side socket that will read + + private final byte[] serverMsg = "Hi there Client, I'm a Server".getBytes(); + private final byte[] clientMsg = "Hello Server, I'm a Client".getBytes(); + + private ByteBuffer serverOut; // write side of serverEngine + private ByteBuffer serverIn; // read side of serverEngine + + private volatile Exception clientException; + private volatile Exception serverException; + + /* + * For data transport, this example uses local ByteBuffers. + */ + private ByteBuffer cTOs; // "reliable" transport client->server + private ByteBuffer sTOc; // "reliable" transport server->client + + /* + * The following is to set up the keystores/trust material. + */ + private static final String pathToStores = "../../../../../../../etc/"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + private static String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + private static String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + String [] protocols = new String [] { + "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }; + + for (String protocol : protocols) { + log("Testing " + protocol); + /* + * Run the tests with direct and indirect buffers. + */ + SSLEngineBadBufferArrayAccess test = + new SSLEngineBadBufferArrayAccess(protocol); + test.runTest(true); + test.runTest(false); + } + + System.out.println("Test Passed."); + } + + /* + * Create an initialized SSLContext to use for these tests. + */ + public SSLEngineBadBufferArrayAccess(String protocol) throws Exception { + + KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ts = KeyStore.getInstance("JKS"); + + char[] passphrase = "passphrase".toCharArray(); + + ks.load(new FileInputStream(keyFilename), passphrase); + ts.load(new FileInputStream(trustFilename), passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance(protocol); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + sslc = sslCtx; + } + + /* + * Run the test. + * + * Sit in a tight loop, with the server engine calling wrap/unwrap + * regardless of whether data is available or not. We do this until + * we get the application data. Then we shutdown and go to the next one. + * + * The main loop handles all of the I/O phases of the SSLEngine's + * lifetime: + * + * initial handshaking + * application data transfer + * engine closing + * + * One could easily separate these phases into separate + * sections of code. + */ + private void runTest(boolean direct) throws Exception { + boolean serverClose = direct; + + serverSocket = new ServerSocket(0); + int port = serverSocket.getLocalPort(); + Thread thread = createClientThread(port, serverClose); + + socket = serverSocket.accept(); + socket.setSoTimeout(500); + serverSocket.close(); + + createSSLEngine(); + createBuffers(direct); + + try { + boolean closed = false; + + InputStream is = socket.getInputStream(); + OutputStream os = socket.getOutputStream(); + + SSLEngineResult serverResult; // results from last operation + + /* + * Examining the SSLEngineResults could be much more involved, + * and may alter the overall flow of the application. + * + * For example, if we received a BUFFER_OVERFLOW when trying + * to write to the output pipe, we could reallocate a larger + * pipe, but instead we wait for the peer to drain it. + */ + byte[] inbound = new byte[8192]; + byte[] outbound = new byte[8192]; + + while (!isEngineClosed(serverEngine)) { + int len = 0; + + // Inbound data + log("================"); + + // Read from the Client side. + try { + len = is.read(inbound); + if (len == -1) { + throw new Exception("Unexpected EOF"); + } + cTOs.put(inbound, 0, len); + } catch (SocketTimeoutException ste) { + // swallow. Nothing yet, probably waiting on us. + } + + cTOs.flip(); + + serverResult = serverEngine.unwrap(cTOs, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + cTOs.compact(); + + // Outbound data + log("----"); + + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + + sTOc.flip(); + + if ((len = sTOc.remaining()) != 0) { + sTOc.get(outbound, 0, len); + os.write(outbound, 0, len); + // Give the other side a chance to process + } + + sTOc.compact(); + + if (!closed && (serverOut.remaining() == 0)) { + closed = true; + + /* + * We'll alternate initiatating the shutdown. + * When the server initiates, it will take one more + * loop, but tests the orderly shutdown. + */ + if (serverClose) { + serverEngine.closeOutbound(); + } + serverIn.flip(); + + /* + * A sanity check to ensure we got what was sent. + */ + if (serverIn.remaining() != clientMsg.length) { + throw new Exception("Client: Data length error"); + } + + for (int i = 0; i < clientMsg.length; i++) { + if (clientMsg[i] != serverIn.get()) { + throw new Exception("Client: Data content error"); + } + } + serverIn.compact(); + } + } + return; + } catch (Exception e) { + serverException = e; + } finally { + socket.close(); + + // Wait for the client to join up with us. + thread.join(); + if (serverException != null) { + throw serverException; + } + if (clientException != null) { + throw clientException; + } + } + } + + /* + * Create a client thread which does simple SSLSocket operations. + * We'll write and read one data packet. + */ + private Thread createClientThread(final int port, + final boolean serverClose) throws Exception { + + Thread t = new Thread("ClientThread") { + + @Override + public void run() { + try { + Thread.sleep(1000); // Give server time to finish setup. + + sslSocket = (SSLSocket) sslc.getSocketFactory(). + createSocket("localhost", port); + OutputStream os = sslSocket.getOutputStream(); + InputStream is = sslSocket.getInputStream(); + + // write(byte[]) goes in one shot. + os.write(clientMsg); + + byte[] inbound = new byte[2048]; + int pos = 0; + + int len; +done: + while ((len = is.read(inbound, pos, 2048 - pos)) != -1) { + pos += len; + // Let the client do the closing. + if ((pos == serverMsg.length) && !serverClose) { + sslSocket.close(); + break done; + } + } + + if (pos != serverMsg.length) { + throw new Exception("Client: Data length error"); + } + + for (int i = 0; i < serverMsg.length; i++) { + if (inbound[i] != serverMsg[i]) { + throw new Exception("Client: Data content error"); + } + } + } catch (Exception e) { + clientException = e; + } + } + }; + t.start(); + return t; + } + + /* + * Using the SSLContext created during object creation, + * create/configure the SSLEngines we'll use for this test. + */ + private void createSSLEngine() throws Exception { + /* + * Configure the serverEngine to act as a server in the SSL/TLS + * handshake. + */ + serverEngine = sslc.createSSLEngine(); + serverEngine.setUseClientMode(false); + serverEngine.getNeedClientAuth(); + } + + /* + * Create and size the buffers appropriately. + */ + private void createBuffers(boolean direct) { + + SSLSession session = serverEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); + + /* + * We'll make the input buffers a bit bigger than the max needed + * size, so that unwrap()s following a successful data transfer + * won't generate BUFFER_OVERFLOWS. + * + * We'll use a mix of direct and indirect ByteBuffers for + * tutorial purposes only. In reality, only use direct + * ByteBuffers when they give a clear performance enhancement. + */ + if (direct) { + serverIn = ByteBuffer.allocateDirect(appBufferMax + 50); + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); + } else { + serverIn = ByteBuffer.allocate(appBufferMax + 50); + cTOs = ByteBuffer.allocate(netBufferMax); + sTOc = ByteBuffer.allocate(netBufferMax); + } + + serverOut = ByteBuffer.wrap(serverMsg); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static boolean isEngineClosed(SSLEngine engine) { + return (engine.isOutboundDone() && engine.isInboundDone()); + } + + /* + * Logging code + */ + private static boolean resultOnce = true; + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + if (resultOnce) { + resultOnce = false; + System.out.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } +}