< prev index next >
src/share/classes/javax/crypto/Cipher.java
Print this page
rev 1386 : 7092825: javax.crypto.Cipher.Transform.patternCache is synchronizedMap and became scalability bottleneck.
Summary: Changed patternCache from synchronizedMap to ConcurrentHashMap.
Reviewed-by: mullan
rev 1387 : 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
Reviewed-by: xuelei, mullan
Contributed-by: alexandre.boulgakov@oracle.com
*** 1,7 ****
/*
! * Copyright (c) 1997, 2007, 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
--- 1,7 ----
/*
! * Copyright (c) 1997, 2012, 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
*** 24,36 ****
*/
package javax.crypto;
import java.util.*;
import java.util.regex.*;
- import static java.util.Locale.ENGLISH;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
--- 24,37 ----
*/
package javax.crypto;
import java.util.*;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
import java.util.regex.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
*** 42,52 ****
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import sun.security.util.Debug;
import sun.security.jca.*;
- import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of a cryptographic cipher for
* encryption and decryption. It forms the core of the Java Cryptographic
* Extension (JCE) framework.
--- 43,52 ----
*** 171,184 ****
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
! private Iterator serviceIterator;
// list of transform Strings to lookup in the provider
! private List transforms;
private final Object lock;
/**
* Creates a Cipher object.
--- 171,184 ----
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
! private Iterator<Service> serviceIterator;
// list of transform Strings to lookup in the provider
! private List<Transform> transforms;
private final Object lock;
/**
* Creates a Cipher object.
*** 215,225 ****
this.cryptoPerm = CryptoAllPermission.INSTANCE;
this.lock = null;
}
private Cipher(CipherSpi firstSpi, Service firstService,
! Iterator serviceIterator, String transformation, List transforms) {
this.firstSpi = firstSpi;
this.firstService = firstService;
this.serviceIterator = serviceIterator;
this.transforms = transforms;
this.transformation = transformation;
--- 215,226 ----
this.cryptoPerm = CryptoAllPermission.INSTANCE;
this.lock = null;
}
private Cipher(CipherSpi firstSpi, Service firstService,
! Iterator<Service> serviceIterator, String transformation,
! List<Transform> transforms) {
this.firstSpi = firstSpi;
this.firstService = firstService;
this.serviceIterator = serviceIterator;
this.transforms = transforms;
this.transformation = transformation;
*** 334,360 ****
return S_MAYBE;
}
return matches(regexp, value) ? S_YES : S_NO;
}
! // Map<String,Pattern> for previously compiled patterns
! // XXX use ConcurrentHashMap once available
! private final static Map patternCache =
! Collections.synchronizedMap(new HashMap());
private static boolean matches(String regexp, String str) {
! Pattern pattern = (Pattern)patternCache.get(regexp);
if (pattern == null) {
pattern = Pattern.compile(regexp);
! patternCache.put(regexp, pattern);
}
return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();
}
}
! private static List getTransforms(String transformation)
throws NoSuchAlgorithmException {
String[] parts = tokenizeTransformation(transformation);
String alg = parts[0];
String mode = parts[1];
--- 335,360 ----
return S_MAYBE;
}
return matches(regexp, value) ? S_YES : S_NO;
}
! // ConcurrentMap<String,Pattern> for previously compiled patterns
! private final static ConcurrentMap<String, Pattern> patternCache =
! new ConcurrentHashMap<String, Pattern>();
private static boolean matches(String regexp, String str) {
! Pattern pattern = patternCache.get(regexp);
if (pattern == null) {
pattern = Pattern.compile(regexp);
! patternCache.putIfAbsent(regexp, pattern);
}
return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();
}
}
! private static List<Transform> getTransforms(String transformation)
throws NoSuchAlgorithmException {
String[] parts = tokenizeTransformation(transformation);
String alg = parts[0];
String mode = parts[1];
*** 370,393 ****
// DES
Transform tr = new Transform(alg, "", null, null);
return Collections.singletonList(tr);
} else { // if ((mode != null) && (pad != null)) {
// DES/CBC/PKCS5Padding
! List list = new ArrayList(4);
list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
list.add(new Transform(alg, "/" + mode, null, pad));
list.add(new Transform(alg, "//" + pad, mode, null));
list.add(new Transform(alg, "", mode, pad));
return list;
}
}
// get the transform matching the specified service
! private static Transform getTransform(Service s, List transforms) {
String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);
! for (Iterator t = transforms.iterator(); t.hasNext(); ) {
! Transform tr = (Transform)t.next();
if (alg.endsWith(tr.suffix)) {
return tr;
}
}
return null;
--- 370,393 ----
// DES
Transform tr = new Transform(alg, "", null, null);
return Collections.singletonList(tr);
} else { // if ((mode != null) && (pad != null)) {
// DES/CBC/PKCS5Padding
! List<Transform> list = new ArrayList<Transform>(4);
list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
list.add(new Transform(alg, "/" + mode, null, pad));
list.add(new Transform(alg, "//" + pad, mode, null));
list.add(new Transform(alg, "", mode, pad));
return list;
}
}
// get the transform matching the specified service
! private static Transform getTransform(Service s,
! List<Transform> transforms) {
String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);
! for (Transform tr : transforms) {
if (alg.endsWith(tr.suffix)) {
return tr;
}
}
return null;
*** 427,449 ****
* @see java.security.Provider
*/
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException
{
! List transforms = getTransforms(transformation);
! List cipherServices = new ArrayList(transforms.size());
! for (Iterator t = transforms.iterator(); t.hasNext(); ) {
! Transform transform = (Transform)t.next();
cipherServices.add(new ServiceId("Cipher", transform.transform));
}
! List services = GetInstance.getServices(cipherServices);
// make sure there is at least one service from a signed provider
// and that it can use the specified mode and padding
! Iterator t = services.iterator();
Exception failure = null;
while (t.hasNext()) {
! Service s = (Service)t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
Transform tr = getTransform(s, transforms);
if (tr == null) {
--- 427,448 ----
* @see java.security.Provider
*/
public static final Cipher getInstance(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException
{
! List<Transform> transforms = getTransforms(transformation);
! List<ServiceId> cipherServices = new ArrayList<ServiceId>(transforms.size());
! for (Transform transform : transforms) {
cipherServices.add(new ServiceId("Cipher", transform.transform));
}
! List<Service> services = GetInstance.getServices(cipherServices);
// make sure there is at least one service from a signed provider
// and that it can use the specified mode and padding
! Iterator<Service> t = services.iterator();
Exception failure = null;
while (t.hasNext()) {
! Service s = t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
Transform tr = getTransform(s, transforms);
if (tr == null) {
*** 567,581 ****
{
if (provider == null) {
throw new IllegalArgumentException("Missing provider");
}
Exception failure = null;
! List transforms = getTransforms(transformation);
boolean providerChecked = false;
String paddingError = null;
! for (Iterator t = transforms.iterator(); t.hasNext();) {
! Transform tr = (Transform)t.next();
Service s = provider.getService("Cipher", tr.transform);
if (s == null) {
continue;
}
if (providerChecked == false) {
--- 566,579 ----
{
if (provider == null) {
throw new IllegalArgumentException("Missing provider");
}
Exception failure = null;
! List<Transform> transforms = getTransforms(transformation);
boolean providerChecked = false;
String paddingError = null;
! for (Transform tr : transforms) {
Service s = provider.getService("Cipher", tr.transform);
if (s == null) {
continue;
}
if (providerChecked == false) {
*** 674,684 ****
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
! s = (Service)serviceIterator.next();
thisSpi = null;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
--- 672,682 ----
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
! s = serviceIterator.next();
thisSpi = null;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
*** 768,778 ****
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
! s = (Service)serviceIterator.next();
thisSpi = null;
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
--- 766,776 ----
s = firstService;
thisSpi = firstSpi;
firstService = null;
firstSpi = null;
} else {
! s = serviceIterator.next();
thisSpi = null;
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
*** 1530,1540 ****
// type X.509.
if (certificate instanceof java.security.cert.X509Certificate) {
// Check whether the cert has a key usage extension
// marked as a critical extension.
X509Certificate cert = (X509Certificate)certificate;
! Set critSet = cert.getCriticalExtensionOIDs();
if (critSet != null && !critSet.isEmpty()
&& critSet.contains(KEY_USAGE_EXTENSION_OID)) {
boolean[] keyUsageInfo = cert.getKeyUsage();
// keyUsageInfo[2] is for keyEncipherment;
--- 1528,1538 ----
// type X.509.
if (certificate instanceof java.security.cert.X509Certificate) {
// Check whether the cert has a key usage extension
// marked as a critical extension.
X509Certificate cert = (X509Certificate)certificate;
! Set<String> critSet = cert.getCriticalExtensionOIDs();
if (critSet != null && !critSet.isEmpty()
&& critSet.contains(KEY_USAGE_EXTENSION_OID)) {
boolean[] keyUsageInfo = cert.getKeyUsage();
// keyUsageInfo[2] is for keyEncipherment;
< prev index next >