Merge "Fix CTS test failure under ART"
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
index f71acb1..e4caffa 100644
--- a/libart/src/main/java/java/lang/DexCache.java
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -71,7 +71,7 @@
String[] strings;
/** Holds C pointer to dexFile. */
- private int dexFile;
+ private long dexFile;
// Only created by the VM.
private DexCache() {}
diff --git a/libart/src/main/java/java/lang/Thread.java b/libart/src/main/java/java/lang/Thread.java
index 5c81e36..2cc2857 100644
--- a/libart/src/main/java/java/lang/Thread.java
+++ b/libart/src/main/java/java/lang/Thread.java
@@ -124,8 +124,8 @@
*/
public static final int NORM_PRIORITY = 5;
- /* some of these are accessed directly by the VM; do not rename them */
- private volatile int nativePeer;
+ /* Some of these are accessed directly by the VM; do not rename them. */
+ private volatile long nativePeer;
volatile ThreadGroup group;
volatile boolean daemon;
volatile String name;
diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java
index 9e90c8f..c88daef 100644
--- a/libart/src/main/java/java/lang/reflect/ArtMethod.java
+++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java
@@ -42,38 +42,99 @@
* @hide
*/
public final class ArtMethod {
+ /* A note on the field order here, it reflects the same field order as laid out by ART. */
/** Method's declaring class */
private Class<?> declaringClass;
- /** Method access flags (modifiers) */
- private int accessFlags;
- /** DexFile index */
- private int methodDexIndex;
- /** Dispatch table entry */
- private int methodIndex;
- /** DexFile offset of CodeItem for this Method */
- private int codeItemOffset;
- /* ART compiler meta-data */
- private int frameSizeInBytes;
- private int coreSpillMask;
- private int fpSpillMask;
- private int mappingTable;
- private int gcMap;
- private int vmapTable;
- /** ART: compiled managed code associated with this Method */
- private int entryPointFromCompiledCode;
- /** ART: entry point from interpreter associated with this Method */
- private int entryPointFromInterpreter;
- /** ART: if this is a native method, the native code that will be invoked */
- private int nativeMethod;
- /* ART: dex cache fast access */
- private String[] dexCacheStrings;
- Class<?>[] dexCacheResolvedTypes;
+
+ /** Short-cut to declaringClass.dexCache.resolvedMethods */
private ArtMethod[] dexCacheResolvedMethods;
+ /** Short-cut to declaringClass.dexCache.resolvedTypes */
+ /* package */ Class<?>[] dexCacheResolvedTypes;
+
+ /** Short-cut to declaringClass.dexCache.strings */
+ private String[] dexCacheStrings;
+
/**
- * Only created by art directly.
+ * Method dispatch from the interpreter invokes this pointer which may cause a bridge into
+ * compiled code.
*/
+ private long entryPointFromInterpreter;
+
+ /**
+ * Pointer to JNI function registered to this method, or a function to resolve the JNI function.
+ */
+ private long entryPointFromJni;
+
+ /**
+ * Method dispatch from portable compiled code invokes this pointer which may cause bridging
+ * into quick compiled code or the interpreter.
+ */
+ private long entryPointFromPortableCompiledCode;
+
+ /**
+ * Method dispatch from quick compiled code invokes this pointer which may cause bridging
+ * into portable compiled code or the interpreter.
+ */
+ private long entryPointFromQuickCompiledCode;
+
+ /**
+ * Pointer to a data structure created by the compiler and used by the garbage collector to
+ * determine which registers hold live references to objects within the heap.
+ */
+ private long gcMap;
+
+ /* Quick compiler meta-data. TODO: merge and place in native heap. */
+
+ /**
+ * Pointer to a data structure created by the quick compiler to map between dex PCs and
+ * native PCs, and vice-versa.
+ */
+ private long quickMappingTable;
+
+ /**
+ * Pointer to a data structure used by the quick compiler to map between dalvik and machine
+ * registers.
+ */
+ private long quickVmapTable;
+
+ /* End of quick compiler meta-data. */
+
+ /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
+ private int accessFlags;
+
+ /* Dex file fields. The defining dex file is available via declaringClass.dexCache */
+
+ /** The offset of the code item associated with this method within its defining dex file */
+ private int dexCodeItemOffset;
+
+ /** The method index of this method within its defining dex file */
+ private int dexMethodIndex;
+
+ /* End of dex file fields. */
+
+ /**
+ * Entry within a dispatch table for this method. For static/direct methods the index is
+ * into the declaringClass.directMethods, for virtual methods the vtable and for
+ * interface methods the ifTable.
+ */
+ private int methodIndex;
+
+ /* Quick compiler meta-data. TODO: merge and place in native heap. */
+
+ /** Bit map of spilled machine registers. */
+ private int quickCoreSpillMask;
+
+ /** Bit map of spilled floating point machine registers. */
+ private int quickFpSpillMask;
+
+ /** Fixed frame size for this method when executed. */
+ private int quickFrameSizeInBytes;
+
+ /* End of quick compiler meta-data. */
+
+ /** Only created by ART directly. */
private ArtMethod() {}
Class getDeclaringClass() {
@@ -85,7 +146,7 @@
}
int getDexMethodIndex() {
- return methodDexIndex;
+ return dexMethodIndex;
}
public static String getMethodName(ArtMethod artMethod) {
@@ -126,7 +187,7 @@
Class<?>[] getParameterTypes() {
Dex dex = getDeclaringClass().getDex();
- short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
if (types.length == 0) {
return EmptyArray.CLASS;
}
@@ -140,7 +201,7 @@
Class<?> getReturnType() {
Dex dex = declaringClass.getDex();
- int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
+ int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex);
// Note, in the case of a Proxy the dex cache types are equal.
return getDexCacheType(dex, returnTypeIndex);
}
@@ -152,7 +213,7 @@
*/
int compareParameters(Class<?>[] params) {
Dex dex = getDeclaringClass().getDex();
- short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
int length = Math.min(types.length, params.length);
for (int i = 0; i < length; i++) {
Class<?> aType = getDexCacheType(dex, types[i]);
@@ -168,7 +229,7 @@
}
Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(declaringClass, methodDexIndex);
+ return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex);
}
/**
@@ -210,7 +271,7 @@
// Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
// Method refers to the original interface's dex cache and is ensured to be resolved by
// proxy generation.
- return dexCacheResolvedMethods[methodDexIndex];
+ return dexCacheResolvedMethods[dexMethodIndex];
}
return this;
}
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index 1147291..e70898b 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -21,11 +21,11 @@
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import org.apache.harmony.security.fortress.Engine;
-
/**
* {@code Signature} is an engine class which is capable of creating and
* verifying digital signatures, using different algorithms that have been
@@ -39,13 +39,13 @@
private static final String SERVICE = "Signature";
// Used to access common engine functionality
- private static Engine ENGINE = new Engine(SERVICE);
+ private static final Engine ENGINE = new Engine(SERVICE);
// The provider
- private Provider provider;
+ Provider provider;
// The algorithm.
- private String algorithm;
+ final String algorithm;
/**
* Constant that indicates that this {@code Signature} instance has not yet
@@ -101,16 +101,7 @@
if (algorithm == null) {
throw new NullPointerException("algorithm == null");
}
- Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
- Object spi = sap.spi;
- Provider provider = sap.provider;
- if (spi instanceof Signature) {
- Signature result = (Signature) spi;
- result.algorithm = algorithm;
- result.provider = provider;
- return result;
- }
- return new SignatureImpl((SignatureSpi) spi, provider, algorithm);
+ return getSignature(algorithm, null);
}
/**
@@ -143,7 +134,7 @@
if (p == null) {
throw new NoSuchProviderException(provider);
}
- return getSignatureInstance(algorithm, p);
+ return getSignature(algorithm, p);
}
/**
@@ -171,19 +162,64 @@
if (provider == null) {
throw new IllegalArgumentException("provider == null");
}
- return getSignatureInstance(algorithm, provider);
+ return getSignature(algorithm, provider);
}
- private static Signature getSignatureInstance(String algorithm,
- Provider provider) throws NoSuchAlgorithmException {
- Object spi = ENGINE.getInstance(algorithm, provider, null);
- if (spi instanceof Signature) {
- Signature result = (Signature) spi;
- result.algorithm = algorithm;
- result.provider = provider;
- return result;
+ private static Signature getSignature(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ if (algorithm == null || algorithm.isEmpty()) {
+ throw new NoSuchAlgorithmException("Unknown algorithm: " + algorithm);
}
- return new SignatureImpl((SignatureSpi) spi, provider, algorithm);
+
+ if (tryAlgorithm(null, provider, algorithm) == null) {
+ if (provider == null) {
+ throw new NoSuchAlgorithmException("No provider found for " + algorithm);
+ } else {
+ throw new NoSuchAlgorithmException("Provider " + provider.getName()
+ + " does not provide " + algorithm);
+ }
+ }
+ return new SignatureImpl(algorithm, provider);
+ }
+
+ private static Engine.SpiAndProvider tryAlgorithm(Key key, Provider provider, String algorithm) {
+ if (provider != null) {
+ Provider.Service service = provider.getService(SERVICE, algorithm);
+ if (service == null) {
+ return null;
+ }
+ return tryAlgorithmWithProvider(key, service);
+ }
+ ArrayList<Provider.Service> services = ENGINE.getServices(algorithm);
+ if (services == null) {
+ return null;
+ }
+ for (Provider.Service service : services) {
+ Engine.SpiAndProvider sap = tryAlgorithmWithProvider(key, service);
+ if (sap != null) {
+ return sap;
+ }
+ }
+ return null;
+ }
+
+ private static Engine.SpiAndProvider tryAlgorithmWithProvider(Key key, Provider.Service service) {
+ try {
+ if (key != null && !service.supportsParameter(key)) {
+ return null;
+ }
+
+ Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
+ if (sap.spi == null || sap.provider == null) {
+ return null;
+ }
+ if (!(sap.spi instanceof SignatureSpi)) {
+ return null;
+ }
+ return sap;
+ } catch (NoSuchAlgorithmException ignored) {
+ }
+ return null;
}
/**
@@ -192,10 +228,18 @@
* @return the provider associated with this {@code Signature}.
*/
public final Provider getProvider() {
+ ensureProviderChosen();
return provider;
}
/**
+ * This makes sure the provider is chosen since Signature is abstract and
+ * getProvider is final but we need to support late binding.
+ */
+ void ensureProviderChosen() {
+ }
+
+ /**
* Returns the name of the algorithm of this {@code Signature}.
*
* @return the name of the algorithm of this {@code Signature}.
@@ -238,10 +282,10 @@
public final void initVerify(Certificate certificate)
throws InvalidKeyException {
if (certificate instanceof X509Certificate) {
- Set ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
+ Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
boolean critical = false;
if (ce != null && !ce.isEmpty()) {
- for (Iterator i = ce.iterator(); i.hasNext();) {
+ for (Iterator<String> i = ce.iterator(); i.hasNext();) {
if ("2.5.29.15".equals(i.next())) {
//KeyUsage OID = 2.5.29.15
critical = true;
@@ -584,79 +628,117 @@
}
/**
- *
* Internal Signature implementation
- *
*/
private static class SignatureImpl extends Signature {
- private final SignatureSpi spiImpl;
+ /**
+ * Lock held while the SPI is initializing.
+ */
+ private final Object initLock = new Object();
- public SignatureImpl(SignatureSpi signatureSpi, Provider provider,
- String algorithm) {
+ // The provider specified when creating this instance.
+ private final Provider specifiedProvider;
+
+ private SignatureSpi spiImpl;
+
+ public SignatureImpl(String algorithm, Provider provider) {
super(algorithm);
- super.provider = provider;
- spiImpl = signatureSpi;
+ this.specifiedProvider = provider;
+ }
+
+ private SignatureImpl(String algorithm, Provider provider, SignatureSpi spi) {
+ this(algorithm, provider);
+ spiImpl = spi;
+ }
+
+ @Override
+ void ensureProviderChosen() {
+ getSpi(null);
}
@Override
protected byte[] engineSign() throws SignatureException {
- return spiImpl.engineSign();
+ return getSpi().engineSign();
}
@Override
protected void engineUpdate(byte arg0) throws SignatureException {
- spiImpl.engineUpdate(arg0);
+ getSpi().engineUpdate(arg0);
}
@Override
protected boolean engineVerify(byte[] arg0) throws SignatureException {
- return spiImpl.engineVerify(arg0);
+ return getSpi().engineVerify(arg0);
}
@Override
- protected void engineUpdate(byte[] arg0, int arg1, int arg2)
- throws SignatureException {
- spiImpl.engineUpdate(arg0, arg1, arg2);
+ protected void engineUpdate(byte[] arg0, int arg1, int arg2) throws SignatureException {
+ getSpi().engineUpdate(arg0, arg1, arg2);
}
@Override
- protected void engineInitSign(PrivateKey arg0)
- throws InvalidKeyException {
- spiImpl.engineInitSign(arg0);
+ protected void engineInitSign(PrivateKey arg0) throws InvalidKeyException {
+ getSpi(arg0).engineInitSign(arg0);
}
@Override
- protected void engineInitVerify(PublicKey arg0)
- throws InvalidKeyException {
- spiImpl.engineInitVerify(arg0);
+ protected void engineInitVerify(PublicKey arg0) throws InvalidKeyException {
+ getSpi(arg0).engineInitVerify(arg0);
}
@Override
- protected Object engineGetParameter(String arg0)
- throws InvalidParameterException {
- return spiImpl.engineGetParameter(arg0);
+ protected Object engineGetParameter(String arg0) throws InvalidParameterException {
+ return getSpi().engineGetParameter(arg0);
}
@Override
protected void engineSetParameter(String arg0, Object arg1)
throws InvalidParameterException {
- spiImpl.engineSetParameter(arg0, arg1);
+ getSpi().engineSetParameter(arg0, arg1);
}
@Override
protected void engineSetParameter(AlgorithmParameterSpec arg0)
throws InvalidAlgorithmParameterException {
- spiImpl.engineSetParameter(arg0);
+ getSpi().engineSetParameter(arg0);
}
@Override
public Object clone() throws CloneNotSupportedException {
if (spiImpl instanceof Cloneable) {
SignatureSpi spi = (SignatureSpi) spiImpl.clone();
- return new SignatureImpl(spi, getProvider(), getAlgorithm());
+ return new SignatureImpl(getAlgorithm(), getProvider(), spiImpl);
}
throw new CloneNotSupportedException();
}
+
+ /**
+ * Makes sure a CipherSpi that matches this type is selected.
+ */
+ private SignatureSpi getSpi(Key key) {
+ synchronized (initLock) {
+ if (spiImpl != null && key == null) {
+ return spiImpl;
+ }
+
+ final Engine.SpiAndProvider sap = tryAlgorithm(key, specifiedProvider, algorithm);
+ if (sap == null) {
+ throw new ProviderException("No provider for " + getAlgorithm());
+ }
+
+ spiImpl = (SignatureSpi) sap.spi;
+ provider = sap.provider;
+
+ return spiImpl;
+ }
+ }
+
+ /**
+ * Convenience call when the Key is not available.
+ */
+ private SignatureSpi getSpi() {
+ return getSpi(null);
+ }
}
}
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index 9ddf5ea..9bca45e 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -129,6 +129,11 @@
private Provider provider;
/**
+ * The provider specified when instance created.
+ */
+ private final Provider specifiedProvider;
+
+ /**
* The SPI implementation.
*/
private CipherSpi spiImpl;
@@ -170,7 +175,7 @@
if (!(cipherSpi instanceof NullCipherSpi) && provider == null) {
throw new NullPointerException("provider == null");
}
- this.provider = provider;
+ this.specifiedProvider = provider;
this.spiImpl = cipherSpi;
this.transformation = transformation;
this.transformParts = null;
@@ -179,7 +184,7 @@
private Cipher(String transformation, String[] transformParts, Provider provider) {
this.transformation = transformation;
this.transformParts = transformParts;
- this.provider = provider;
+ this.specifiedProvider = provider;
}
@@ -332,11 +337,12 @@
*/
private CipherSpi getSpi(Key key) {
synchronized (initLock) {
- if (spiImpl != null) {
+ if (spiImpl != null && key == null) {
return spiImpl;
}
- final Engine.SpiAndProvider sap = tryCombinations(key, provider, transformParts);
+ final Engine.SpiAndProvider sap = tryCombinations(key, specifiedProvider,
+ transformParts);
if (sap == null) {
throw new ProviderException("No provider for " + transformation);
}
@@ -436,10 +442,10 @@
Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
if (sap.spi == null || sap.provider == null) {
- return sap;
+ return null;
}
if (!(sap.spi instanceof CipherSpi)) {
- return sap;
+ return null;
}
CipherSpi spi = (CipherSpi) sap.spi;
if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH))
@@ -475,7 +481,7 @@
/**
* Returns the provider of this cipher instance.
- *
+ *
* @return the provider of this cipher instance.
*/
public final Provider getProvider() {
diff --git a/luni/src/main/java/javax/crypto/KeyAgreement.java b/luni/src/main/java/javax/crypto/KeyAgreement.java
index dc3fa2f..abcfd0e 100644
--- a/luni/src/main/java/javax/crypto/KeyAgreement.java
+++ b/luni/src/main/java/javax/crypto/KeyAgreement.java
@@ -23,9 +23,11 @@
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
+import java.security.ProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
import org.apache.harmony.security.fortress.Engine;
/**
@@ -35,22 +37,33 @@
*/
public class KeyAgreement {
+ // The service name.
+ private static final String SERVICE = "KeyAgreement";
+
// Used to access common engine functionality
- private static final Engine ENGINE = new Engine("KeyAgreement");
+ private static final Engine ENGINE = new Engine(SERVICE);
// Store SecureRandom
private static final SecureRandom RANDOM = new SecureRandom();
// Store used provider
- private final Provider provider;
+ private Provider provider;
+
+ // Provider that was requested during creation.
+ private final Provider specifiedProvider;
// Store used spi implementation
- private final KeyAgreementSpi spiImpl;
+ private KeyAgreementSpi spiImpl;
// Store used algorithm name
private final String algorithm;
/**
+ * Lock held while the SPI is initializing.
+ */
+ private final Object initLock = new Object();
+
+ /**
* Creates a new {@code KeyAgreement} instance.
*
* @param keyAgreeSpi
@@ -62,9 +75,9 @@
*/
protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
String algorithm) {
- this.provider = provider;
- this.algorithm = algorithm;
this.spiImpl = keyAgreeSpi;
+ this.specifiedProvider = provider;
+ this.algorithm = algorithm;
}
/**
@@ -82,6 +95,7 @@
* @return the provider for this {@code KeyAgreement} instance.
*/
public final Provider getProvider() {
+ getSpi();
return provider;
}
@@ -96,13 +110,8 @@
* @throws NullPointerException
* if the specified algorithm is {@code null}.
*/
- public static final KeyAgreement getInstance(String algorithm)
- throws NoSuchAlgorithmException {
- if (algorithm == null) {
- throw new NullPointerException("algorithm == null");
- }
- Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
- return new KeyAgreement((KeyAgreementSpi) sap.spi, sap.provider, algorithm);
+ public static final KeyAgreement getInstance(String algorithm) throws NoSuchAlgorithmException {
+ return getKeyAgreement(algorithm, null);
}
/**
@@ -124,9 +133,8 @@
* @throws IllegalArgumentException
* if the specified provider name is {@code null} or empty.
*/
- public static final KeyAgreement getInstance(String algorithm,
- String provider) throws NoSuchAlgorithmException,
- NoSuchProviderException {
+ public static final KeyAgreement getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
if (provider == null || provider.isEmpty()) {
throw new IllegalArgumentException("Provider is null or empty");
}
@@ -134,7 +142,7 @@
if (impProvider == null) {
throw new NoSuchProviderException(provider);
}
- return getInstance(algorithm, impProvider);
+ return getKeyAgreement(algorithm, impProvider);
}
/**
@@ -156,29 +164,108 @@
* @throws NullPointerException
* if the specified algorithm name is {@code null}.
*/
- public static final KeyAgreement getInstance(String algorithm,
- Provider provider) throws NoSuchAlgorithmException {
+ public static final KeyAgreement getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
if (provider == null) {
throw new IllegalArgumentException("provider == null");
}
+ return getKeyAgreement(algorithm, provider);
+ }
+
+ private static KeyAgreement getKeyAgreement(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
if (algorithm == null) {
throw new NullPointerException("algorithm == null");
}
- Object spi = ENGINE.getInstance(algorithm, provider, null);
- return new KeyAgreement((KeyAgreementSpi) spi, provider, algorithm);
+
+ if (tryAlgorithm(null, provider, algorithm) == null) {
+ if (provider == null) {
+ throw new NoSuchAlgorithmException("No provider found for " + algorithm);
+ } else {
+ throw new NoSuchAlgorithmException("Provider " + provider.getName()
+ + " does not provide " + algorithm);
+ }
+ }
+ return new KeyAgreement(null, provider, algorithm);
+ }
+
+ private static Engine.SpiAndProvider tryAlgorithm(Key key, Provider provider, String algorithm) {
+ if (provider != null) {
+ Provider.Service service = provider.getService(SERVICE, algorithm);
+ if (service == null) {
+ return null;
+ }
+ return tryAlgorithmWithProvider(key, service);
+ }
+ ArrayList<Provider.Service> services = ENGINE.getServices(algorithm);
+ if (services == null) {
+ return null;
+ }
+ for (Provider.Service service : services) {
+ Engine.SpiAndProvider sap = tryAlgorithmWithProvider(key, service);
+ if (sap != null) {
+ return sap;
+ }
+ }
+ return null;
+ }
+
+ private static Engine.SpiAndProvider tryAlgorithmWithProvider(Key key, Provider.Service service) {
+ try {
+ if (key != null && !service.supportsParameter(key)) {
+ return null;
+ }
+
+ Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
+ if (sap.spi == null || sap.provider == null) {
+ return null;
+ }
+ if (!(sap.spi instanceof KeyAgreementSpi)) {
+ return null;
+ }
+ return sap;
+ } catch (NoSuchAlgorithmException ignored) {
+ }
+ return null;
+ }
+
+ /**
+ * Makes sure a KeyAgreementSpi that matches this type is selected.
+ */
+ private KeyAgreementSpi getSpi(Key key) {
+ synchronized (initLock) {
+ if (spiImpl != null && key == null) {
+ return spiImpl;
+ }
+
+ final Engine.SpiAndProvider sap = tryAlgorithm(key, specifiedProvider, algorithm);
+ if (sap == null) {
+ throw new ProviderException("No provider for " + getAlgorithm());
+ }
+
+ spiImpl = (KeyAgreementSpi) sap.spi;
+ provider = sap.provider;
+
+ return spiImpl;
+ }
+ }
+
+ /**
+ * Convenience call when the Key is not available.
+ */
+ private KeyAgreementSpi getSpi() {
+ return getSpi(null);
}
/**
* Initializes this {@code KeyAgreement} with the specified key.
*
- * @param key
- * the key to initialize this key agreement.
- * @throws InvalidKeyException
- * if the specified key cannot be used to initialize this key
- * agreement.
+ * @param key the key to initialize this key agreement.
+ * @throws InvalidKeyException if the specified key cannot be used to
+ * initialize this key agreement.
*/
public final void init(Key key) throws InvalidKeyException {
- spiImpl.engineInit(key, RANDOM);//new SecureRandom());
+ getSpi(key).engineInit(key, RANDOM);//new SecureRandom());
}
/**
@@ -195,7 +282,7 @@
*/
public final void init(Key key, SecureRandom random)
throws InvalidKeyException {
- spiImpl.engineInit(key, random);
+ getSpi(key).engineInit(key, random);
}
/**
@@ -215,7 +302,7 @@
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- spiImpl.engineInit(key, params, RANDOM);//new SecureRandom());
+ getSpi(key).engineInit(key, params, RANDOM);//new SecureRandom());
}
/**
@@ -238,7 +325,7 @@
public final void init(Key key, AlgorithmParameterSpec params,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
- spiImpl.engineInit(key, params, random);
+ getSpi(key).engineInit(key, params, random);
}
/**
@@ -260,7 +347,7 @@
*/
public final Key doPhase(Key key, boolean lastPhase)
throws InvalidKeyException, IllegalStateException {
- return spiImpl.engineDoPhase(key, lastPhase);
+ return getSpi().engineDoPhase(key, lastPhase);
}
/**
@@ -271,7 +358,7 @@
* if this key agreement is not complete.
*/
public final byte[] generateSecret() throws IllegalStateException {
- return spiImpl.engineGenerateSecret();
+ return getSpi().engineGenerateSecret();
}
/**
@@ -290,7 +377,7 @@
*/
public final int generateSecret(byte[] sharedSecret, int offset)
throws IllegalStateException, ShortBufferException {
- return spiImpl.engineGenerateSecret(sharedSecret, offset);
+ return getSpi().engineGenerateSecret(sharedSecret, offset);
}
/**
@@ -312,7 +399,7 @@
public final SecretKey generateSecret(String algorithm)
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException {
- return spiImpl.engineGenerateSecret(algorithm);
+ return getSpi().engineGenerateSecret(algorithm);
}
}
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index 073eb2d..2c94882 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -171,10 +171,8 @@
* by {@code toString}. This is very lenient, and doesn't care what's between the underscores:
* this method can parse strings that {@code Locale.toString} won't produce.
* Used to remove duplication.
- *
- * Package visible for testing.
*/
- static Locale localeFromIcuLocaleId(String localeId) {
+ public static Locale localeFromIcuLocaleId(String localeId) {
// @ == ULOC_KEYWORD_SEPARATOR_UNICODE (uloc.h).
final int extensionsIndex = localeId.indexOf('@');
diff --git a/luni/src/main/java/libcore/io/StructStat.java b/luni/src/main/java/libcore/io/StructStat.java
index 05ecca7..00371fb 100644
--- a/luni/src/main/java/libcore/io/StructStat.java
+++ b/luni/src/main/java/libcore/io/StructStat.java
@@ -70,7 +70,7 @@
/** Number of blocks allocated for this object. */
public final long st_blocks; /*blkcnt_t*/
- StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid,
+ public StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid,
long st_rdev, long st_size, long st_atime, long st_mtime, long st_ctime,
long st_blksize, long st_blocks) {
this.st_dev = st_dev;
diff --git a/luni/src/main/java/libcore/io/StructStatVfs.java b/luni/src/main/java/libcore/io/StructStatVfs.java
index bb78ff2..bdff111 100644
--- a/luni/src/main/java/libcore/io/StructStatVfs.java
+++ b/luni/src/main/java/libcore/io/StructStatVfs.java
@@ -53,7 +53,7 @@
/** Maximum filename length. */
public final long f_namemax; /*unsigned long*/
- StructStatVfs(long f_bsize, long f_frsize, long f_blocks, long f_bfree, long f_bavail,
+ public StructStatVfs(long f_bsize, long f_frsize, long f_blocks, long f_bfree, long f_bavail,
long f_files, long f_ffree, long f_favail,
long f_fsid, long f_flag, long f_namemax) {
this.f_bsize = f_bsize;
diff --git a/luni/src/main/java/libcore/io/StructUcred.java b/luni/src/main/java/libcore/io/StructUcred.java
index 359995d..c13212c 100644
--- a/luni/src/main/java/libcore/io/StructUcred.java
+++ b/luni/src/main/java/libcore/io/StructUcred.java
@@ -29,7 +29,7 @@
/** The peer process' gid. */
public final int gid;
- private StructUcred(int pid, int uid, int gid) {
+ public StructUcred(int pid, int uid, int gid) {
this.pid = pid;
this.uid = uid;
this.gid = gid;
diff --git a/luni/src/main/java/libcore/io/StructUtsname.java b/luni/src/main/java/libcore/io/StructUtsname.java
index e6a8e42..d7d606b 100644
--- a/luni/src/main/java/libcore/io/StructUtsname.java
+++ b/luni/src/main/java/libcore/io/StructUtsname.java
@@ -37,7 +37,7 @@
/** The machine architecture, such as "armv7l" or "x86_64". */
public final String machine;
- StructUtsname(String sysname, String nodename, String release, String version, String machine) {
+ public StructUtsname(String sysname, String nodename, String release, String version, String machine) {
this.sysname = sysname;
this.nodename = nodename;
this.release = release;
diff --git a/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java b/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
index 006dda8..855a8c7 100644
--- a/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
+++ b/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
@@ -69,7 +69,7 @@
*
* }</pre>
*/
-public class Engine {
+public final class Engine {
/**
* Access to package visible api in java.security
diff --git a/luni/src/test/java/libcore/java/security/MockPrivateKey.java b/luni/src/test/java/libcore/java/security/MockPrivateKey.java
new file mode 100644
index 0000000..e5ac797
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/MockPrivateKey.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import java.security.PrivateKey;
+
+/**
+ * A mock PrivateKey class used for testing.
+ */
+@SuppressWarnings("serial")
+public class MockPrivateKey implements PrivateKey {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ return "MOCK";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/MockPrivateKey2.java b/luni/src/test/java/libcore/java/security/MockPrivateKey2.java
new file mode 100644
index 0000000..a1c02c9
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/MockPrivateKey2.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import java.security.PrivateKey;
+
+/**
+ * A mock PrivateKey class used for testing.
+ */
+@SuppressWarnings("serial")
+public class MockPrivateKey2 implements PrivateKey {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ return "MOCK";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/MockPublicKey.java b/luni/src/test/java/libcore/java/security/MockPublicKey.java
new file mode 100644
index 0000000..130b461
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/MockPublicKey.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import java.security.PublicKey;
+
+/**
+ * A mock PublicKey class used for testing.
+ */
+@SuppressWarnings("serial")
+public class MockPublicKey implements PublicKey {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ return "MOCK";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/MockSignatureSpi.java b/luni/src/test/java/libcore/java/security/MockSignatureSpi.java
new file mode 100644
index 0000000..6017547
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/MockSignatureSpi.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+
+/**
+ * Mock SignatureSpi used by {@link SignatureTest}.
+ */
+public class MockSignatureSpi extends SignatureSpi {
+ public static class SpecificKeyTypes extends MockSignatureSpi {
+ @Override
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ if (!(key instanceof MockPrivateKey)) {
+ throw new InvalidKeyException("Must be MockPrivateKey!");
+ }
+ }
+ }
+
+ public static class SpecificKeyTypes2 extends MockSignatureSpi {
+ @Override
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ if (!(key instanceof MockPrivateKey2)) {
+ throw new InvalidKeyException("Must be MockPrivateKey2!");
+ }
+ }
+ }
+
+ public static class AllKeyTypes extends MockSignatureSpi {
+ }
+
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineInitVerify(java.security.PublicKey)
+ */
+ @Override
+ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey)
+ */
+ @Override
+ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+ checkKeyType(privateKey);
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineUpdate(byte)
+ */
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineSign()
+ */
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineVerify(byte[])
+ */
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineSetParameter(java.lang.String, java.lang.Object)
+ */
+ @Override
+ protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineGetParameter(java.lang.String)
+ */
+ @Override
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineUpdate(byte[], int, int)
+ */
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 1027dd4..9c5738b 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -18,6 +18,7 @@
import java.math.BigInteger;
import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -38,10 +39,192 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-
import junit.framework.TestCase;
public class SignatureTest extends TestCase {
+ private static abstract class MockProvider extends Provider {
+ public MockProvider(String name) {
+ super(name, 1.0, "Mock provider used for testing");
+ setup();
+ }
+
+ public abstract void setup();
+ }
+
+ public void testSignature_getInstance_SuppliedProviderNotRegistered_Success() throws Exception {
+ Provider mockProvider = new MockProvider("MockProvider") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ {
+ Signature s = Signature.getInstance("FOO", mockProvider);
+ s.initSign(new MockPrivateKey());
+ assertEquals(mockProvider, s.getProvider());
+ }
+ }
+
+ public void testSignature_getInstance_OnlyUsesSpecifiedProvider_SameNameAndClass_Success()
+ throws Exception {
+ Provider mockProvider = new MockProvider("MockProvider") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProvider);
+ try {
+ {
+ Provider mockProvider2 = new MockProvider("MockProvider") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
+ }
+ };
+ Signature s = Signature.getInstance("FOO", mockProvider2);
+ assertEquals(mockProvider2, s.getProvider());
+ }
+ } finally {
+ Security.removeProvider(mockProvider.getName());
+ }
+ }
+
+ public void testSignature_getInstance_DelayedInitialization_KeyType() throws Exception {
+ Provider mockProviderSpecific = new MockProvider("MockProviderSpecific") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.SpecificKeyTypes.class.getName());
+ put("Signature.FOO SupportedKeyClasses", MockPrivateKey.class.getName());
+ }
+ };
+ Provider mockProviderSpecific2 = new MockProvider("MockProviderSpecific2") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.SpecificKeyTypes2.class.getName());
+ put("Signature.FOO SupportedKeyClasses", MockPrivateKey2.class.getName());
+ }
+ };
+ Provider mockProviderAll = new MockProvider("MockProviderAll") {
+ public void setup() {
+ put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderSpecific);
+ Security.addProvider(mockProviderSpecific2);
+ Security.addProvider(mockProviderAll);
+
+ try {
+ {
+ Signature s = Signature.getInstance("FOO");
+ s.initSign(new MockPrivateKey());
+ assertEquals(mockProviderSpecific, s.getProvider());
+
+ try {
+ s.initSign(new MockPrivateKey2());
+ assertEquals(mockProviderSpecific2, s.getProvider());
+ if (StandardNames.IS_RI) {
+ fail("RI was broken before; fix tests now that it works!");
+ }
+ } catch (InvalidKeyException e) {
+ if (!StandardNames.IS_RI) {
+ fail("Non-RI should select the right provider");
+ }
+ }
+ }
+
+ {
+ Signature s = Signature.getInstance("FOO");
+ s.initSign(new PrivateKey() {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+ });
+ assertEquals(mockProviderAll, s.getProvider());
+ }
+
+ {
+ Signature s = Signature.getInstance("FOO");
+ assertEquals(mockProviderSpecific, s.getProvider());
+ }
+ } finally {
+ Security.removeProvider(mockProviderSpecific.getName());
+ Security.removeProvider(mockProviderSpecific2.getName());
+ Security.removeProvider(mockProviderAll.getName());
+ }
+ }
+
+ private static class MySignature extends Signature {
+ protected MySignature(String algorithm) {
+ super(algorithm);
+ }
+
+ @Override
+ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void engineSetParameter(String param, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void testSignature_getProvider_Subclass() throws Exception {
+ Provider mockProviderNonSpi = new MockProvider("MockProviderNonSpi") {
+ public void setup() {
+ put("Signature.FOO", MySignature.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderNonSpi);
+
+ try {
+ Signature s = new MySignature("FOO");
+ assertNull(s.getProvider());
+ } finally {
+ Security.removeProvider(mockProviderNonSpi.getName());
+ }
+ }
// 20 bytes for DSA
private final byte[] DATA = new byte[20];
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 21cc5da..f7a0a72 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -890,7 +890,13 @@
Provider mockProviderSpecific = new MockProvider("MockProviderSpecific") {
public void setup() {
put("Cipher.FOO", MockCipherSpi.SpecificKeyTypes.class.getName());
- put("Cipher.FOO SupportedKeyClasses", this.getClass().getPackage().getName() + ".MockKey");
+ put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
+ }
+ };
+ Provider mockProviderSpecific2 = new MockProvider("MockProviderSpecific2") {
+ public void setup() {
+ put("Cipher.FOO", MockCipherSpi.SpecificKeyTypes2.class.getName());
+ put("Cipher.FOO SupportedKeyClasses", MockKey2.class.getName());
}
};
Provider mockProviderAll = new MockProvider("MockProviderAll") {
@@ -900,13 +906,27 @@
};
Security.addProvider(mockProviderSpecific);
+ Security.addProvider(mockProviderSpecific2);
Security.addProvider(mockProviderAll);
try {
{
+ System.out.println(Arrays.deepToString(Security.getProviders("Cipher.FOO")));
Cipher c = Cipher.getInstance("FOO");
c.init(Cipher.ENCRYPT_MODE, new MockKey());
assertEquals(mockProviderSpecific, c.getProvider());
+
+ try {
+ c.init(Cipher.ENCRYPT_MODE, new MockKey2());
+ assertEquals(mockProviderSpecific2, c.getProvider());
+ if (StandardNames.IS_RI) {
+ fail("RI was broken before; fix tests now that it works!");
+ }
+ } catch (InvalidKeyException e) {
+ if (!StandardNames.IS_RI) {
+ fail("Non-RI should select the right provider");
+ }
+ }
}
{
@@ -936,10 +956,28 @@
}
} finally {
Security.removeProvider(mockProviderSpecific.getName());
+ Security.removeProvider(mockProviderSpecific2.getName());
Security.removeProvider(mockProviderAll.getName());
}
}
+ public void testCipher_getInstance_WrongType_Failure() throws Exception {
+ Provider mockProviderInvalid = new MockProvider("MockProviderInvalid") {
+ public void setup() {
+ put("Cipher.FOO", Object.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderInvalid);
+ try {
+ Cipher.getInstance("FOO");
+ fail("Should not find any matching providers");
+ } catch (NoSuchAlgorithmException expected) {
+ } finally {
+ Security.removeProvider(mockProviderInvalid.getName());
+ }
+ }
+
public void test_getInstance() throws Exception {
final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
PrintStream out = new PrintStream(errBuffer);
diff --git a/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java b/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
index eb950cc..6742cf3 100644
--- a/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
+++ b/luni/src/test/java/libcore/javax/crypto/MockCipherSpi.java
@@ -38,7 +38,17 @@
@Override
public void checkKeyType(Key key) throws InvalidKeyException {
if (!(key instanceof MockKey)) {
- throw new InvalidKeyException("Must be a mock key!");
+ throw new InvalidKeyException("Must be MockKey!");
+ }
+ }
+ }
+
+ public static class SpecificKeyTypes2 extends MockCipherSpi {
+ @Override
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ System.err.println("Checking key of type " + key.getClass().getName());
+ if (!(key instanceof MockKey2)) {
+ throw new InvalidKeyException("Must be MockKey2!");
}
}
}
diff --git a/luni/src/test/java/libcore/javax/crypto/MockKey2.java b/luni/src/test/java/libcore/javax/crypto/MockKey2.java
new file mode 100644
index 0000000..44ac0cc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/crypto/MockKey2.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.javax.crypto;
+
+import java.security.Key;
+
+/**
+ * A mock Key class used for testing.
+ */
+@SuppressWarnings("serial")
+public class MockKey2 implements Key {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ return "MOCK";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/KeyAgreementTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/KeyAgreementTest.java
index 99d127a..0642229 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/KeyAgreementTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/KeyAgreementTest.java
@@ -22,6 +22,8 @@
package org.apache.harmony.crypto.tests.javax.crypto;
+import org.apache.harmony.security.tests.support.SpiEngUtils;
+import org.apache.harmony.security.tests.support.TestKeyPair;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -31,6 +33,7 @@
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
@@ -40,12 +43,10 @@
import javax.crypto.ShortBufferException;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.spec.DHParameterSpec;
-
-import org.apache.harmony.crypto.tests.support.MyKeyAgreementSpi;
-import org.apache.harmony.security.tests.support.SpiEngUtils;
-import org.apache.harmony.security.tests.support.TestKeyPair;
-
import junit.framework.TestCase;
+import libcore.java.security.StandardNames;
+import libcore.javax.crypto.MockKey;
+import libcore.javax.crypto.MockKey2;
/**
@@ -676,4 +677,127 @@
//expected
}
}
+
+ private static abstract class MockProvider extends Provider {
+ public MockProvider(String name) {
+ super(name, 1.0, "Mock provider used for testing");
+ setup();
+ }
+
+ public abstract void setup();
+ }
+
+ public void testKeyAgreement_getInstance_SuppliedProviderNotRegistered_Success()
+ throws Exception {
+ Provider mockProvider = new MockProvider("MockProvider") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ {
+ KeyAgreement s = KeyAgreement.getInstance("FOO", mockProvider);
+ s.init(new MockKey());
+ assertEquals(mockProvider, s.getProvider());
+ }
+ }
+
+ public void testKeyAgreement_getInstance_OnlyUsesSpecifiedProvider_SameNameAndClass_Success()
+ throws Exception {
+ Provider mockProvider = new MockProvider("MockProvider") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProvider);
+ try {
+ {
+ Provider mockProvider2 = new MockProvider("MockProvider") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
+ }
+ };
+ KeyAgreement s = KeyAgreement.getInstance("FOO", mockProvider2);
+ assertEquals(mockProvider2, s.getProvider());
+ }
+ } finally {
+ Security.removeProvider(mockProvider.getName());
+ }
+ }
+
+ public void testKeyAgreement_getInstance_DelayedInitialization_KeyType() throws Exception {
+ Provider mockProviderSpecific = new MockProvider("MockProviderSpecific") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.SpecificKeyTypes.class.getName());
+ put("KeyAgreement.FOO SupportedKeyClasses", MockKey.class.getName());
+ }
+ };
+ Provider mockProviderSpecific2 = new MockProvider("MockProviderSpecific2") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.SpecificKeyTypes2.class.getName());
+ put("KeyAgreement.FOO SupportedKeyClasses", MockKey2.class.getName());
+ }
+ };
+ Provider mockProviderAll = new MockProvider("MockProviderAll") {
+ public void setup() {
+ put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderSpecific);
+ Security.addProvider(mockProviderSpecific2);
+ Security.addProvider(mockProviderAll);
+
+ try {
+ {
+ KeyAgreement s = KeyAgreement.getInstance("FOO");
+ s.init(new MockKey());
+ assertEquals(mockProviderSpecific, s.getProvider());
+
+ try {
+ s.init(new MockKey2());
+ assertEquals(mockProviderSpecific2, s.getProvider());
+ if (StandardNames.IS_RI) {
+ fail("RI was broken before; fix tests now that it works!");
+ }
+ } catch (InvalidKeyException e) {
+ if (!StandardNames.IS_RI) {
+ fail("Non-RI should select the right provider");
+ }
+ }
+ }
+
+ {
+ KeyAgreement s = KeyAgreement.getInstance("FOO");
+ s.init(new PrivateKey() {
+ @Override
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getFormat() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+ });
+ assertEquals(mockProviderAll, s.getProvider());
+ }
+
+ {
+ KeyAgreement s = KeyAgreement.getInstance("FOO");
+ assertEquals(mockProviderSpecific, s.getProvider());
+ }
+ } finally {
+ Security.removeProvider(mockProviderSpecific.getName());
+ Security.removeProvider(mockProviderSpecific2.getName());
+ Security.removeProvider(mockProviderAll.getName());
+ }
+ }
+
}
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MockKeyAgreementSpi.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MockKeyAgreementSpi.java
new file mode 100644
index 0000000..4b53a6b
--- /dev/null
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MockKeyAgreementSpi.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.crypto.tests.javax.crypto;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.KeyAgreementSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import libcore.javax.crypto.MockKey;
+import libcore.javax.crypto.MockKey2;
+
+public class MockKeyAgreementSpi extends KeyAgreementSpi {
+ public static class SpecificKeyTypes extends MockKeyAgreementSpi {
+ @Override
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ if (!(key instanceof MockKey)) {
+ throw new InvalidKeyException("Must be MockKey!");
+ }
+ }
+ }
+
+ public static class SpecificKeyTypes2 extends MockKeyAgreementSpi {
+ @Override
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ if (!(key instanceof MockKey2)) {
+ throw new InvalidKeyException("Must be MockKey2!");
+ }
+ }
+ }
+
+ public static class AllKeyTypes extends MockKeyAgreementSpi {
+ }
+
+ public void checkKeyType(Key key) throws InvalidKeyException {
+ }
+
+ @Override
+ protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException,
+ IllegalStateException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected int engineGenerateSecret(byte[] sharedSecret, int offset)
+ throws IllegalStateException, ShortBufferException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
+ checkKeyType(key);
+ }
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ checkKeyType(key);
+ }
+}