/*
 *  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.
 */

/**
* @author Vera Y. Petrashkova
*/

package org.apache.harmony.security.tests.support;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Additional class for KeyStoreSpi and KeyStore verification
 * 
 */

public class MyKeyStore extends KeyStoreSpi {
    private Hashtable Keys = new Hashtable();

    private Hashtable Cert = new Hashtable();

    private Hashtable Chain = new Hashtable();

    private Hashtable Dates = new Hashtable();

    private Hashtable KeysSL = new Hashtable();

    private Hashtable CertSL = new Hashtable();

    private Hashtable ChainSL = new Hashtable();

    private Hashtable DatesSL = new Hashtable();

    public Key engineGetKey(String alias, char[] password)
            throws NoSuchAlgorithmException, UnrecoverableKeyException {
        if (Keys.containsKey(alias)) {
            return (Key) Keys.get(alias);
        }
        return null;
    }

    public Certificate[] engineGetCertificateChain(String alias) {
        if (Chain.containsKey(alias)) {
            return (Certificate[]) Chain.get(alias);
        }
        return null;
    }

    public Certificate engineGetCertificate(String alias) {
        if (Cert.containsKey(alias)) {
            return (Certificate) Cert.get(alias);
        }
        return null;
    }

    public Date engineGetCreationDate(String alias) {
        if (Dates.containsKey(alias)) {
            return (Date) Dates.get(alias);
        }
        return null;
    }

    public void engineSetKeyEntry(String alias, Key key, char[] password,
            Certificate[] chain) throws KeyStoreException {
        if (Cert.containsKey(alias)) {
            Cert.remove(alias);
        }
        Keys.put(alias, key);
        if (chain != null) {
            Chain.put(alias, chain);
        }
        Dates.put(alias, new Date());
    }

    public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain)
            throws KeyStoreException {
        if (key == null) {
            throw new KeyStoreException("Not Supported for null key");
        }
        if (Cert.containsKey(alias)) {
            Cert.remove(alias);
        }
        if (Chain.containsKey(alias)) {
            Chain.remove(alias);
        }
        KeyStoreTestSupport.MyPrivateKey keyK = new KeyStoreTestSupport.MyPrivateKey(
                alias, alias, key);
        Keys.put(alias, keyK);
        if (chain != null) {
            Chain.put(alias, chain);
        }
        Dates.put(alias, new Date());

    }

    public void engineSetCertificateEntry(String alias, Certificate cert)
            throws KeyStoreException {
        Cert.put(alias, cert);
        Dates.put(alias, new Date());
    }

    public void engineDeleteEntry(String alias) throws KeyStoreException {
        if (Keys.containsKey(alias)) {
            Keys.remove(alias);
            Chain.remove(alias);
            return;
        }
        if (Cert.containsKey(alias)) {
            Cert.remove(alias);
        }
    }

    public Enumeration engineAliases() {
        return null;
    }

    public boolean engineContainsAlias(String alias) {
        if (Keys.containsKey(alias)) {
            return true;
        }
        if (Cert.containsKey(alias)) {
            return true;
        }
        return false;
    }

    public int engineSize() {
        return (Keys.size() + Cert.size());
    }

    public boolean engineIsKeyEntry(String alias) {
        if (Keys.containsKey(alias)) {
            return true;
        }
        return false;
    }

    public boolean engineIsCertificateEntry(String alias) {
        if (Cert.containsKey(alias)) {
            return true;
        }
        return false;
    }

    public String engineGetCertificateAlias(Certificate cert) {
        return "";
    }

    public void engineStore(OutputStream stream, char[] password)
            throws IOException, NoSuchAlgorithmException, CertificateException {
        if (!(stream instanceof ByteArrayOutputStream)) {
            throw new IOException("Incorrect stream");
        }
        String alias;
        Enumeration e = Keys.keys();
        while (e.hasMoreElements()) {
            alias = (String) e.nextElement();
            KeysSL.put(alias, Keys.get(alias));
            DatesSL.put(alias, Dates.get(alias));
            if (Chain.containsKey(alias)) {
                ChainSL.put(alias, Chain.get(alias));
            }
        }
        e = Cert.keys();
        while (e.hasMoreElements()) {
            alias = (String) e.nextElement();
            CertSL.put(alias, Cert.get(alias));
            DatesSL.put(alias, Dates.get(alias));
        }
    }

    public void engineLoad(InputStream stream, char[] password)
            throws IOException, NoSuchAlgorithmException, CertificateException {
        Keys.clear();
        Cert.clear();
        Chain.clear();
        Dates.clear();
        String alias;
        Enumeration e = KeysSL.keys();
        while (e.hasMoreElements()) {
            alias = (String) e.nextElement();
            Keys.put(alias, KeysSL.get(alias));
            Dates.put(alias, DatesSL.get(alias));
            if (ChainSL.containsKey(alias)) {
                Chain.put(alias, ChainSL.get(alias));
            }
        }
        e = CertSL.keys();
        while (e.hasMoreElements()) {
            alias = (String) e.nextElement();
            Cert.put(alias, CertSL.get(alias));
            Dates.put(alias, DatesSL.get(alias));
        }
    }

    public void engineStore(KeyStore.LoadStoreParameter param)
            throws IOException, NoSuchAlgorithmException, CertificateException {
        if (param == null) {
            throw new IOException("param is null");
        }
    }

    public void engineLoad(KeyStore.LoadStoreParameter param)
            throws IOException, NoSuchAlgorithmException, CertificateException {
        if (!(param instanceof MyLoadStoreParams)) {
            throw new IllegalArgumentException("param is not MyLoadStoreParams: " + param);
        }
    }
}