/****************************************************************************
 * Copyright (C) 2015-2018 ecsec GmbH.
 * All rights reserved.
 * Contact: ecsec GmbH (info@ecsec.de)
 *
 * This file is part of the Open eCard App.
 *
 * GNU General Public License Usage
 * This file may be used under the terms of the GNU General Public
 * License version 3.0 as published by the Free Software Foundation
 * and appearing in the file LICENSE.GPL included in the packaging of
 * this file. Please review the following information to ensure the
 * GNU General Public License version 3.0 requirements will be met:
 * http://www.gnu.org/copyleft/gpl.html.
 *
 * Other Usage
 * Alternatively, this file may be used in accordance with the terms
 * and conditions contained in a signed written agreement between
 * you and ecsec GmbH.
 *
 ***************************************************************************/

package org.openecard.scio;

import java.lang.reflect.Field;
import javax.annotation.Nonnull;
import javax.smartcardio.CardException;
import org.openecard.common.ifd.scio.SCIOErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Helper class to retrieve the actual PCSC error code from the Java SmartcardIO exception.
 *
 * @author Tobias Wich
 */
public class PCSCExceptionExtractor {

    private static final Logger LOG = LoggerFactory.getLogger(PCSCExceptionExtractor.class);

    public static SCIOErrorCode getCode(@Nonnull CardException mainException) {
	return getCode((Exception) mainException);
    }

    /**
     * Gets the actual error code from the given CardException.
     * This method uses reflections to access the actual error code which is hidden in the Java SmartcardIO. In case no
     * error code can be found, {@link SCIOErrorCode#SCARD_F_UNKNOWN_ERROR} is returned.
     *
     * @param mainException The exception coming from the Java SmartcardIO.
     * @return The code extracted from the exception, or {@link SCIOErrorCode#SCARD_F_UNKNOWN_ERROR} if no code could be
     *   extracted.
     */
    public static SCIOErrorCode getCode(@Nonnull Exception mainException) {
	Throwable cause = getPCSCException(mainException);
	// check the type of the cause over reflections because these classes might not be available (sun internal)
	if (cause != null) {
	    try {
		Class<?> c = cause.getClass();
		Field f = c.getDeclaredField("code");
		f.setAccessible(true);
		int code = f.getInt(cause);
		return SCIOErrorCode.getErrorCode(code);
	    } catch (NoSuchFieldException ex) {
		LOG.error("Failed to find field 'code' in PCSCException.");
		// fallthrough as this only reduces the quality of the exceptions
	    } catch (IllegalAccessException ex) {
		LOG.error("Failed to read field 'code' in PCSCException.");
		// fallthrough as this only reduces the quality of the exceptions
	    } catch (SecurityException ex) {
		LOG.error("Failed access field 'code' in PCSCException or change its accessibility.");
		// fallthrough as this only reduces the quality of the exceptions
	    }
	}
	return SCIOErrorCode.SCARD_F_UNKNOWN_ERROR;
    }

    public static boolean hasPCSCException(Exception mainException) {
	return getPCSCException(mainException) != null;
    }

    private static Throwable getPCSCException(Exception mainException) {
	Throwable cause = mainException.getCause();
	// check the type of the cause over reflections because these classes might not be available (sun internal)
	if (cause != null) {
	    Class<?> c = cause.getClass();
	    if ("sun.security.smartcardio.PCSCException".equals(c.getName())) {
		return cause;
	    }
	}

	return null;
    }

}

@@ -932,40 +932,8 @@
 o;%0A%0A
-import java.lang.reflect.Field;%0A
 impo
@@ -2291,347 +2291,57 @@
 %7B%0A%09%09
-Class%3C?%3E c = cause.getClass();%0A%09%09Field f = c.getDeclaredField(%22code%22);%0A%09%09f.setAccessible(true);%0A%09%09int code = f.getInt(cause);%0A%09%09return SCIOErrorCode.getErrorCode(code);%0A%09    %7D catch (NoSuchFieldException ex) %7B%0A%09%09LOG.error(%22Failed to find field 'code' in PCSCException.%22);%0A%09%09// fallthrough as this only reduces the quality of the exceptions
+return SCIOErrorCode.valueOf(cause.getMessage());
 %0A%09  
@@ -2359,21 +2359,23 @@
 IllegalA
-ccess
+rgument
 Exceptio
@@ -2388,342 +2388,74 @@
 %7B%0A%09%09
-LOG.error(%22Failed to read field 'code' in PCSCException.%22);%0A%09%09// fallthrough as this only reduces the quality of the exceptions%0A%09    %7D catch (SecurityException ex) %7B%0A%09%09LOG.error(%22Failed access field 'code' in PCSCException or change its accessibility.%22);%0A%09%09// fallthrough as this only reduces the quality of the exceptions%0A%09    %7D%0A%09%7D%0A%09
+return SCIOErrorCode.SCARD_F_UNKNOWN_ERROR;%0A%09    %7D%0A%09%7D else %7B%0A%09    
 retu
@@ -2494,16 +2494,19 @@
 _ERROR;%0A
+%09%7D%0A
     %7D%0A%0A 

Remove reflective access to PCSCException 'code' field