/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.security.tests.java.security;

import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyFactorySpi;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;

@TestTargetClass(KeyFactory.class)
public class KeyFactory2Test extends junit.framework.TestCase {

    private static final String KEYFACTORY_ID = "KeyFactory.";

    private String[] keyfactAlgs = null;

    private String providerName = null;

    static class KeepAlive extends Thread {
        int sleepTime, iterations;

        public KeepAlive(int sleepTime, int iterations) {
            this.sleepTime = sleepTime;
            this.iterations = iterations;
        }

        public void run() {
            synchronized (this) {
                this.notify();
            }
            for (int i = 0; i < iterations; i++) {
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }

    private KeepAlive createKeepAlive(String alg) {
        if (alg.equals("RSA")) {
            // 32 minutes
            KeepAlive keepalive = new KeepAlive(240000, 8);
            synchronized (keepalive) {
                keepalive.start();
                try {
                    keepalive.wait();
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            return keepalive;
        }
        return null;
    }

    /**
     * @tests java.security.KeyFactory#KeyFactory(java.security.KeyFactorySpi,
     *        java.security.Provider, java.lang.String)
     */
    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "",
        method = "KeyFactory",
        args = {java.security.KeyFactorySpi.class, java.security.Provider.class, java.lang.String.class}
    )
    public void test_constructor() {
        KeyFactorySpi kfs = new KeyFactorySpiStub();

        try {
            new KeyFactoryStub(null, null, null);
        } catch (Exception e) {
            fail("Unexpected exception " + e.getMessage());
        }

        Provider[] providers = Security.getProviders("KeyFactory.DSA");
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                KeyFactoryStub kf = new KeyFactoryStub(kfs, providers[i],
                        "algorithm name");
                assertEquals("algorithm name", kf.getAlgorithm());
                assertEquals(providers[i], kf.getProvider());
            }
        } else {
            fail("No providers support KeyFactory.DSA");
        }
    }

    /**
     * @tests java.security.KeyFactory#generatePrivate(java.security.spec.KeySpec)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "",
        method = "generatePrivate",
        args = {java.security.spec.KeySpec.class}
    )
    public void test_generatePrivateLjava_security_spec_KeySpec() {
        // Test for method java.security.PrivateKey
        // java.security.KeyFactory.generatePrivate(java.security.spec.KeySpec)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);
                SecureRandom random = new SecureRandom(); // We don't use
                // getInstance
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }

                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
                        getPrivateKeySpecClass(keyfactAlgs[i]));
                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
                boolean samePrivate = Arrays.equals(keys.getPrivate()
                        .getEncoded(), privateKey.getEncoded());
                assertTrue(
                        "generatePrivate generated different key for algorithm "
                                + keyfactAlgs[i], samePrivate);
                fact.generatePrivate(new PKCS8EncodedKeySpec(keys.getPrivate()
                        .getEncoded()));

            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#generatePublic(java.security.spec.KeySpec)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "InvalidKeySpecException checking missed",
        method = "generatePublic",
        args = {java.security.spec.KeySpec.class}
    )
    public void test_generatePublicLjava_security_spec_KeySpec() {
        // Test for method java.security.PublicKey
        // java.security.KeyFactory.generatePublic(java.security.spec.KeySpec)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);
                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
                        getPublicKeySpecClass(keyfactAlgs[i]));
                PublicKey publicKey = fact.generatePublic(publicKeySpec);
                boolean samePublic = Arrays.equals(keys.getPublic()
                        .getEncoded(), publicKey.getEncoded());
                assertTrue(
                        "generatePublic generated different key for algorithm "
                                + keyfactAlgs[i], samePublic);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#getAlgorithm()
     */
    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "",
        method = "getAlgorithm",
        args = {}
    )
    public void test_getAlgorithm() {
        // Test for method java.lang.String
        // java.security.KeyFactory.getAlgorithm()
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                assertTrue("getAlgorithm ok for algorithm " + keyfactAlgs[i],
                        fact.getAlgorithm().equals(keyfactAlgs[i]));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#getInstance(java.lang.String)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "NoSuchAlgorithmException checking missed",
        method = "getInstance",
        args = {java.lang.String.class}
    )
    public void test_getInstanceLjava_lang_String() {
        // Test for method java.security.KeyFactory
        // java.security.KeyFactory.getInstance(java.lang.String)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                assertNotNull(KeyFactory.getInstance(keyfactAlgs[i]));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#getInstance(java.lang.String,
     *        java.lang.String)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "NoSuchAlgorithmException, NoSuchProviderException checking missed",
        method = "getInstance",
        args = {java.lang.String.class, java.lang.String.class}
    )
    public void test_getInstanceLjava_lang_StringLjava_lang_String() {

        // Test1: Test for method java.security.KeyFactory
        // java.security.KeyFactory.getInstance(java.lang.String,
        // java.lang.String)
        try {
            Provider[] providers = Security.getProviders("KeyFactory.DSA");
            if (providers != null) {
                for (int i = 0; i < providers.length; i++) {
                    KeyFactory.getInstance("DSA", providers[i].getName());
                }// end for
            } else {
                fail("No providers support KeyFactory.DSA");
            }
        } catch (NoSuchAlgorithmException e) {
            fail("getInstance did not find algorithm");
        } catch (NoSuchProviderException e) {
            fail("getInstance did not find the provider");
        }

        // Test2: Test with null provider name
        try {
            KeyFactory.getInstance("DSA", (String) null);
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // Expected
        } catch (Exception e) {
            fail("Expected IllegalArgumentException, got " + e);
        }
    }

    /**
     * @tests java.security.KeyFactory#getInstance(java.lang.String, Provider)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "NoSuchAlgorithmException checking missed",
        method = "getInstance",
        args = {java.lang.String.class, java.security.Provider.class}
    )
    public void test_getInstanceLjava_lang_StringLjava_security_Provider() {

        // Test1: Test for method java.security.KeyFactory
        // java.security.KeyFactory.getInstance(java.lang.String,
        // java.security.Provider)
        try {
            Provider[] providers = Security.getProviders("KeyFactory.DSA");
            if (providers != null) {
                for (int i = 0; i < providers.length; i++) {
                    KeyFactory.getInstance("DSA", providers[i]);
                }// end for
            } else {
                fail("No providers support KeyFactory.DSA");
            }
        } catch (NoSuchAlgorithmException e) {
            fail("getInstance did not find algorithm");
        } catch (Exception e) {
            fail("unexpected exception " + e.getMessage());
        }

        // Test2: Test with null provider name
        try {
            KeyFactory.getInstance("DSA", (Provider) null);
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // Expected
        } catch (Exception e) {
            fail("Expected IllegalArgumentException, got " + e);
        }
    }

    /**
     * @tests java.security.KeyFactory#getKeySpec(java.security.Key,
     *        java.lang.Class)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "InvalidKeySpecException checking missed",
        method = "getKeySpec",
        args = {java.security.Key.class, java.lang.Class.class}
    )
    public void test_getKeySpecLjava_security_KeyLjava_lang_Class() {
        // Test for method java.security.spec.KeySpec
        // java.security.KeyFactory.getKeySpec(java.security.Key,
        // java.lang.Class)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);

                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
                        getPrivateKeySpecClass(keyfactAlgs[i]));
                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
                        getPublicKeySpecClass(keyfactAlgs[i]));
                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
                PublicKey publicKey = fact.generatePublic(publicKeySpec);
                boolean samePublic = Arrays.equals(keys.getPublic()
                        .getEncoded(), publicKey.getEncoded());
                boolean samePrivate = Arrays.equals(keys.getPrivate()
                        .getEncoded(), privateKey.getEncoded());
                assertTrue(
                        "generatePrivate generated different key for algorithm "
                                + keyfactAlgs[i], samePrivate);
                assertTrue(
                        "generatePublic generated different key for algorithm "
                                + keyfactAlgs[i], samePublic);
                KeySpec encodedSpec = fact.getKeySpec(keys.getPublic(),
                        X509EncodedKeySpec.class);
                assertTrue("improper key spec for encoded public key",
                        encodedSpec.getClass().equals(X509EncodedKeySpec.class));
                encodedSpec = fact.getKeySpec(keys.getPrivate(),
                        PKCS8EncodedKeySpec.class);
                assertTrue("improper key spec for encoded private key",
                        encodedSpec.getClass()
                                .equals(PKCS8EncodedKeySpec.class));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#getProvider()
     */
    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "",
        method = "getProvider",
        args = {}
    )
    public void test_getProvider() {
        // Test for method java.security.Provider
        // java.security.KeyFactory.getProvider()
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i]);
                Provider p = fact.getProvider();
                assertNotNull("provider is null for algorithm "
                        + keyfactAlgs[i], p);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#translateKey(java.security.Key)
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "InvalidKeyException checking missed",
        method = "translateKey",
        args = {java.security.Key.class}
    )
    public void test_translateKeyLjava_security_Key() {
        // Test for method java.security.Key
        // java.security.KeyFactory.translateKey(java.security.Key)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);

                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                fact.translateKey(keys.getPrivate());
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeyException e) {
                fail("generatePublic did not generate right spec for algorithm "
                        + keyfactAlgs[i]);
            }
        }
    }

    protected void setUp() {
        if (keyfactAlgs == null) {
            Provider[] providers = Security.getProviders();
            // Arbitrarily use the first provider that supports
            // KeyFactory algorithms
            for (Provider provider : providers) {
                providerName = provider.getName();
                keyfactAlgs = getKeyFactoryAlgorithms(providerName);
                if (keyfactAlgs.length != 0) {
                    break;
                }
            }
        }
    }

    /*
     * Returns the key algorithms that the given provider supports.
     */
    private String[] getKeyFactoryAlgorithms(String providerName) {
        Vector<String> algs = new Vector<String>();

        Provider provider = Security.getProvider(providerName);
        if (provider == null)
            return new String[0];
        Enumeration<Object> e = provider.keys();
        while (e.hasMoreElements()) {
            String algorithm = (String) e.nextElement();
            if (algorithm.startsWith(KEYFACTORY_ID) && !algorithm.contains(" ")) {
                algs.addElement(algorithm.substring(KEYFACTORY_ID.length()));
            }
        }

        return algs.toArray(new String[algs.size()]);
    }

    /**
     * Returns the public key spec class for a given algorithm, or null if it is
     * not known.
     */
    private Class<? extends KeySpec> getPrivateKeySpecClass(String algName) {
        if (algName.equals("RSA")) {
            return java.security.spec.RSAPrivateCrtKeySpec.class;
        }
        if (algName.equals("DSA")) {
            return java.security.spec.DSAPrivateKeySpec.class;
        }
        return null;
    }

    /**
     * Returns the private key spec class for a given algorithm, or null if it
     * is not known.
     */
    private Class<? extends KeySpec> getPublicKeySpecClass(String algName) {
        if (algName.equals("RSA")) {
            return java.security.spec.RSAPublicKeySpec.class;
        }
        if (algName.equals("DSA")) {
            return java.security.spec.DSAPublicKeySpec.class;
        }
        return null;
    }

    public class KeyFactoryStub extends KeyFactory {
        public KeyFactoryStub(KeyFactorySpi keyFacSpi, Provider provider,
                String algorithm) {
            super(keyFacSpi, provider, algorithm);
        }
    }

    public class KeyFactorySpiStub extends KeyFactorySpi {
        public KeyFactorySpiStub() {
            super();
        }

        public PrivateKey engineGeneratePrivate(KeySpec keySpec) {
            return null;
        }

        public PublicKey engineGeneratePublic(KeySpec keySpec) {
            return null;
        }

        public <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) {
            return null;
        }

        public Key engineTranslateKey(Key key) {
            return null;
        }
    }
}
