/*
 *  Copyright 2016
 *
 *  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.acra.security;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import org.acra.ACRA;
import org.acra.ACRAConstants;
import org.acra.util.IOUtils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

import static org.acra.ACRA.LOG_TAG;

/**
 * Provides base KeyStoreFactory implementation
 *
 * @author F43nd1r
 * @since 4.8.3
 */
@SuppressWarnings({"WeakerAccess","unused"})
public abstract class BaseKeyStoreFactory implements KeyStoreFactory {

    private final String certificateType;

    /**
     * creates a new KeyStoreFactory for the default certificate type {@link ACRAConstants#DEFAULT_CERTIFICATE_TYPE}
     */
    public BaseKeyStoreFactory(){
        this(ACRAConstants.DEFAULT_CERTIFICATE_TYPE);
    }

    /**
     * creates a new KeyStoreFactory with the specified certificate type
     * @param certificateType the certificate type
     */
    public BaseKeyStoreFactory(String certificateType) {
        this.certificateType = certificateType;
    }

    abstract public InputStream getInputStream(@NonNull Context context);

    @Override
    @Nullable
    public final KeyStore create(@NonNull Context context) {
        InputStream inputStream = getInputStream(context);
        if (inputStream != null) {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            try {
                CertificateFactory certificateFactory = CertificateFactory.getInstance(certificateType);
                Certificate certificate = certificateFactory.generateCertificate(bufferedInputStream);
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", certificate);
                return keyStore;
            } catch (CertificateException e) {
                ACRA.log.e(LOG_TAG, "Could not load certificate", e);
            } catch (KeyStoreException e) {
                ACRA.log.e(LOG_TAG, "Could not load certificate", e);
            } catch (NoSuchAlgorithmException e) {
                ACRA.log.e(LOG_TAG, "Could not load certificate", e);
            } catch (IOException e) {
                ACRA.log.e(LOG_TAG, "Could not load certificate", e);
            } finally {
                IOUtils.safeClose(bufferedInputStream);
            }
        }
        return null;
    }
}

@@ -1328,16 +1328,17 @@
 Access%22,
+ 
 %22unused%22
@@ -1412,16 +1412,84 @@
 tory %7B%0A%0A
+    public enum Type %7B%0A        CERTIFICATE,%0A        KEYSTORE%0A    %7D%0A%0A
     priv
@@ -1688,16 +1688,17 @@
 actory()
+ 
 %7B%0A      
@@ -1829,24 +1829,31 @@
 ficate type%0A
+     *%0A
      * @para
@@ -2025,21 +2025,24 @@
 stract p
-ublic
+rotected
  InputSt
@@ -2089,16 +2089,248 @@
 text);%0A%0A
+    protected String getKeyStoreType() %7B%0A        return KeyStore.getDefaultType();%0A    %7D%0A%0A    protected Type getStreamType() %7B%0A        return Type.CERTIFICATE;%0A    %7D%0A%0A    protected char%5B%5D getPassword() %7B%0A        return null;%0A    %7D%0A%0A
     @Ove
@@ -2610,24 +2610,190 @@
       try %7B%0A
+                KeyStore keyStore = KeyStore.getInstance(getKeyStoreType());%0A                switch (getStreamType()) %7B%0A                    case CERTIFICATE:%0A        
             
@@ -2881,24 +2881,32 @@
 icateType);%0A
+        
             
@@ -3008,85 +3008,8 @@
     
-        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());%0A
     
@@ -3047,16 +3047,24 @@
  null);%0A
+        
         
@@ -3116,24 +3116,183 @@
 rtificate);%0A
+                        break;%0A                    case KEYSTORE:%0A                        keyStore.load(bufferedInputStream, getPassword());%0A                %7D%0A
             
@@ -3521,34 +3521,31 @@
 ld not load 
-certificat
+keystor
 e%22, e);%0A    
@@ -3639,34 +3639,31 @@
 ld not load 
-certificat
+keystor
 e%22, e);%0A    
@@ -3744,34 +3744,31 @@
 ld not load 
-certificat
+keystor
 e%22, e);%0A    

make BaseKeyStoreFactory more universal