diff options
Diffstat (limited to 'eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential')
3 files changed, 628 insertions, 0 deletions
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java new file mode 100644 index 00000000..5e6ca34b --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java @@ -0,0 +1,257 @@ +package at.gv.egiz.eaaf.core.impl.credential; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +import at.asitplus.hsmfacade.provider.HsmFacadeProvider; +import at.asitplus.hsmfacade.provider.RemoteKeyStoreLoadParameter; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafKeyStoreFactory { + + public static final String CONFIG_PROP_HSM_FACADE_HOST = "security.hsmfacade.host"; + public static final String CONFIG_PROP_HSM_FACADE_PORT = "security.hsmfacade.port"; + public static final String CONFIG_PROP_HSM_FACADE_SSLTRUST = "security.hsmfacade.trustedsslcert"; + public static final String CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME = "security.hsmfacade.username"; + public static final String CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD = "security.hsmfacade.password"; + public static final String CONFIG_PROP_HSM_FACADE_HSM_NAME = "security.hsmfacade.hsmname"; + + public static final String ERRORCODE_00 = "internal.keystore.00"; + public static final String ERRORCODE_01 = "internal.keystore.01"; + public static final String ERRORCODE_02 = "internal.keystore.02"; + public static final String ERRORCODE_03 = "internal.keystore.03"; + public static final String ERRORCODE_04 = "internal.keystore.04"; + public static final String ERRORCODE_05 = "internal.keystore.05"; + public static final String ERRORCODE_06 = "internal.keystore.06"; + public static final String ERRORCODE_07 = "internal.keystore.07"; + + private static final String HSM_FACADE_PROVIDER = "HsmFacade"; + private static final String HSM_FACADE_KEYSTORE_TYPE = "RemoteKeyStore"; + + @Autowired + private IConfiguration basicConfig; + @Autowired + private ResourceLoader resourceLoader; + + private boolean isHsmFacadeInitialized = false; + + /** + * Get a new KeyStore based on a KeyStore configuration-object. + * + * @param config KeyStore configuration + * @return new KeyStore instance + * @throws EaafException In case of a KeyStore initialization error + */ + public KeyStore buildNewKeyStore(KeyStoreConfiguration config) throws EaafException { + log.trace("Starting KeyStore generation based on configuration object ... "); + if (KeyStoreType.PKCS12.equals(config.getKeyStoreType()) + || KeyStoreType.JKS.equals(config.getKeyStoreType())) { + return getKeyStoreFromFileSystem(config); + + } else if (KeyStoreType.HSMFACADE.equals(config.getKeyStoreType())) { + if (isHsmFacadeInitialized) { + return getKeyStoreFromHsmFacade(config); + + } else { + log.error("HSMFacade can NOT be used for KeyStore: {} because {} is not initialized", + config.getFriendlyName()); + throw new EaafConfigurationException(ERRORCODE_00, + new Object[] { config.getFriendlyName() }); + + } + + } else if (KeyStoreType.PKCS11.equals(config.getKeyStoreType())) { + log.warn("KeyStoreType: {} is NOT supported", config.getKeyStoreType()); + throw new EaafConfigurationException(ERRORCODE_02, + new Object[] { config.getFriendlyName(), config.getKeyStoreType() }); + + } else { + log.warn("KeyStoreType: {} is unrecognized", config.getKeyStoreType()); + throw new EaafConfigurationException(ERRORCODE_01, + new Object[] { config.getFriendlyName() }); + + } + } + + /** + * Get the initialization state of the HSM Facade module. + * + * @return true if HSM Facade is available, otherwise false + */ + public boolean isHsmFacadeInitialized() { + return isHsmFacadeInitialized; + + } + + @PostConstruct + private void initialize() throws EaafException { + + final String hsmFacadeHost = basicConfig.getBasicConfiguration(CONFIG_PROP_HSM_FACADE_HOST); + if (StringUtils.isNotEmpty(hsmFacadeHost)) { + log.debug("Find host for HSMFacade. Starting crypto provider initialization ... "); + try { + final int port = Integer.parseUnsignedInt( + getConfigurationParameter(CONFIG_PROP_HSM_FACADE_PORT)); + final String clientUsername = + getConfigurationParameter(CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME); + final String clientPassword = + getConfigurationParameter(CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD); + final String hsmName = + getConfigurationParameter(CONFIG_PROP_HSM_FACADE_HSM_NAME); + + final HsmFacadeProvider provider = HsmFacadeProvider.Companion.getInstance(); + provider.init(getHsmFacadeTrustSslCertificate(), clientUsername, clientPassword, hsmFacadeHost, port, + hsmName); + Security.addProvider(provider); + isHsmFacadeInitialized = true; + log.info("HSM Facade is initialized. {} can provide KeyStores based on remote HSM", + EaafKeyStoreFactory.class.getSimpleName()); + + } catch (final EaafException e) { + throw e; + + } catch (final Exception e) { + log.error("HSM Facade initialization FAILED with an generic error.", e); + throw new EaafConfigurationException(ERRORCODE_03, new Object[] { e.getMessage() }, e); + } + + } else { + log.info("HSM Facade is not configurated. {} can only provide software keystores", + EaafKeyStoreFactory.class.getSimpleName()); + + } + + } + + private KeyStore getKeyStoreFromFileSystem(KeyStoreConfiguration config) throws EaafConfigurationException, + EaafFactoryException { + try { + final String keyStorePath = checkConfigurationParameter(config.getSoftKeyStoreFilePath(), + ERRORCODE_06, config.getFriendlyName(), "Software-KeyStore missing filepath to KeyStore"); + + final String keyStorePassword = checkConfigurationParameter(config.getSoftKeyStorePassword(), + ERRORCODE_06, config.getFriendlyName(), "Software-KeyStore missing Password for KeyStore"); + + final String absKeyStorePath = FileUtils.makeAbsoluteUrl(keyStorePath, basicConfig + .getConfigurationRootDirectory()); + final Resource ressource = resourceLoader.getResource(absKeyStorePath); + if (!ressource.exists()) { + throw new EaafConfigurationException(ERRORCODE_05, + new Object[] { CONFIG_PROP_HSM_FACADE_SSLTRUST, + "File not found at: " + absKeyStorePath }); + + } + + final InputStream is = ressource.getInputStream(); + final KeyStore keyStore = KeyStoreUtils.loadKeyStore(is, keyStorePassword); + is.close(); + if (keyStore == null) { + throw new EaafFactoryException(ERRORCODE_06, + new Object[] { config.getFriendlyName(), "KeyStore not valid or password wrong" }); + + } + + return keyStore; + + } catch (KeyStoreException | IOException e) { + log.error("Software KeyStore initialization FAILED with an generic error.", e); + throw new EaafConfigurationException(ERRORCODE_03, new Object[] { e.getMessage() }, e); + + } + } + + private KeyStore getKeyStoreFromHsmFacade(KeyStoreConfiguration config) + throws EaafFactoryException, EaafConfigurationException { + final String keyStoreName = checkConfigurationParameter(config.getKeyStoreName(), + ERRORCODE_06, config.getFriendlyName(), "KeyStoreName missing for HSM Facade"); + + try { + final KeyStore keyStore = KeyStore.getInstance(HSM_FACADE_KEYSTORE_TYPE, HSM_FACADE_PROVIDER); + keyStore.load(new RemoteKeyStoreLoadParameter(keyStoreName)); + return keyStore; + + } catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException + | NoSuchProviderException e) { + log.error("Can not initialize KeyStore: {} with reason: {}", + config.getFriendlyName(), e.getMessage()); + throw new EaafFactoryException(ERRORCODE_06, + new Object[] { config.getFriendlyName(), e.getMessage() }, e); + + } + } + + private X509Certificate getHsmFacadeTrustSslCertificate() throws EaafConfigurationException { + try { + final String certFilePath = getConfigurationParameter(CONFIG_PROP_HSM_FACADE_SSLTRUST); + + final String absolutCertFilePath = FileUtils.makeAbsoluteUrl( + certFilePath, basicConfig.getConfigurationRootDirectory()); + final Resource certFile = resourceLoader.getResource(absolutCertFilePath); + + if (!certFile.exists()) { + throw new EaafConfigurationException(ERRORCODE_05, + new Object[] { CONFIG_PROP_HSM_FACADE_SSLTRUST, + "File not found at: " + absolutCertFilePath }); + + } + + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certFile + .getInputStream()); + + } catch (final EaafConfigurationException e) { + throw e; + + } catch (CertificateException | IOException e) { + log.error("Can not load trusted server-certificate for HSM-Facade. Reason: {}", e.getMessage()); + throw new EaafConfigurationException(ERRORCODE_05, + new Object[] { CONFIG_PROP_HSM_FACADE_SSLTRUST, e.getMessage() }, e); + + } + } + + @Nonnull + private String getConfigurationParameter(@Nonnull String configParamKey) + throws EaafConfigurationException { + return checkConfigurationParameter( + basicConfig.getBasicConfiguration(configParamKey), ERRORCODE_04, configParamKey); + + } + + @Nonnull + private String checkConfigurationParameter(@Nullable String configParam, @Nonnull String errorCode, + @Nonnull String... errorParams) + throws EaafConfigurationException { + if (StringUtils.isEmpty(configParam)) { + throw new EaafConfigurationException(errorCode, new Object[] { errorParams }); + + } + return configParam; + + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java new file mode 100644 index 00000000..b4b44724 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java @@ -0,0 +1,147 @@ +package at.gv.egiz.eaaf.core.impl.credential; + +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafKeyStoreUtils { + private static final String ERROR_MSG_REASON = "Maybe 'Alias' is not valid"; + private static final String ERROR_MSG_1 = "Can NOT access key: {} in KeyStore: {}. Reason: {}"; + private static final String ERROR_MSG_2 = "Key: {} will be NOT available"; + + /** + * Read all certificates from a {@link KeyStore}. + * + * @param keyStore KeyStore with certificates + * @return {@link List} of {@link X509Certificate}, but never null + * @throws KeyStoreException In case of an error during KeyStore operations + */ + @Nonnull + public static List<X509Certificate> readCertsFromKeyStore(@Nonnull final KeyStore keyStore) throws KeyStoreException { + final List<X509Certificate> result = new ArrayList<>(); + + final Enumeration<String> aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + final String el = aliases.nextElement(); + log.trace("Process TrustStoreEntry: " + el); + if (keyStore.isCertificateEntry(el)) { + final Certificate cert = keyStore.getCertificate(el); + if (cert != null && cert instanceof X509Certificate) { + result.add((X509Certificate) cert); + } else { + log.info("Can not process entry: {}. Reason: {}", el, cert != null ? cert.getType() : "cert is null"); + } + + } + } + + return Collections.unmodifiableList(result); + } + + /** + * Get a specific private Key and the corresponding certificate from a {@link KeyStore}. + * + * @param keyStore KeyStore with certificates + * @param keyAlias Alias of the entry + * @param keyPassword Password to access the Key + * @param isRequired if true, the method throw an {@link EaafKeyAccessException} + * if the key is not available or invalid + * @param friendlyName Name of the KeyStore for logging purposes + * @return A {@link Pair} of {@link Key} and {@link X509Certificate} for this alias, + * or maybe null if isRequired was <code>false</code> + * @throws EaafKeyAccessException In case of an error during KeyStore operations + */ + @Nullable + public static Pair<Key, X509Certificate[]> getPrivateKeyAndCertificates(@Nonnull KeyStore keyStore, + @Nonnull String keyAlias, @Nullable char[] keyPassword, boolean isRequired, @Nonnull String friendlyName) + throws EaafKeyAccessException { + try { + Key privKey = keyStore.getKey(keyAlias, keyPassword); + if (privKey != null) { + final Certificate[] certChainSigning = keyStore.getCertificateChain(keyAlias); + X509Certificate[] certChain = new X509Certificate[certChainSigning.length]; + + for (int i = 0; i < certChainSigning.length; i++) { + if (certChainSigning[i] instanceof X509Certificate) { + certChain[i] = (X509Certificate) certChainSigning[i]; + } else { + log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); + } + + } + + Pair<Key, X509Certificate[]> keyResult = Pair.newInstance(privKey, certChain); + validateKeyResult(keyResult, friendlyName, keyAlias); + return keyResult; + + } else { + if (isRequired) { + log.warn(ERROR_MSG_1, + keyAlias, friendlyName, ERROR_MSG_REASON); + throw new EaafKeyAccessException(EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, ERROR_MSG_REASON); + + } else { + log.info(ERROR_MSG_1, + keyAlias, friendlyName, ERROR_MSG_REASON); + log.info(ERROR_MSG_2, keyAlias); + + } + } + + } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException e) { + if (isRequired) { + log.warn(ERROR_MSG_1, + keyAlias, friendlyName, e.getMessage()); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, e, friendlyName, keyAlias, e.getMessage()); + + } else { + log.info(ERROR_MSG_1, + keyAlias, friendlyName, e.getMessage()); + log.info(ERROR_MSG_2, keyAlias); + + } + } + + return null; + + } + + private static void validateKeyResult(Pair<Key, X509Certificate[]> keyResult, + String friendlyName, String keyAlias) throws EaafKeyAccessException { + // some short validation + if (!(keyResult.getFirst() instanceof PrivateKey)) { + log.info("PrivateKey: {} in KeyStore: {} is of wrong type", keyAlias, friendlyName); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, "Wrong PrivateKey type "); + + } + + if (keyResult.getSecond() == null || keyResult.getSecond().length == 0) { + log.info("NO certificate for Key: {} in KeyStore: {}", keyAlias, friendlyName); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, "NO certificate for PrivateKey"); + + } + } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java new file mode 100644 index 00000000..6dbbba3e --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java @@ -0,0 +1,224 @@ +package at.gv.egiz.eaaf.core.impl.credential; + +import java.util.Map; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +public class KeyStoreConfiguration { + + public static final String PROP_CONFIG_KEYSTORE_TYPE = + "keystore.type"; + + public static final String PROP_CONFIG_HSMFACADE_NAME = + "keystore.name"; + + public static final String PROP_CONFIG_SOFTWARE_KEYSTORE_PATH = + "keystore.path"; + public static final String PROP_CONFIG_SOFTWARE_KEYSTORE_PASSORD = + "keystore.password"; + + /** + * FriendlyName for this KeyStore. Mainly used for logging. + */ + private String friendlyName; + + /** + * General type of the KeyStore that should be generated. + */ + private KeyStoreType keyStoreType; + + /** + * Name of the KeyStore in HSM Facade. + */ + private String keyStoreName; + + /** + * Path to software KeyStore in case of a PKCS12 or JKS KeyStore. + */ + private String softKeyStoreFilePath; + + /** + * Password of a software KeyStore in case of a PKCS12 or JKS KeyStore. + */ + private String softKeyStorePassword; + + /** + * Build a {@link KeyStoreConfiguration} from a configuration map. <br> + * <p> + * The configuration parameters defined in this class are used to load the + * configuration. + * </p> + * + * @param config Configuration + * @param friendlyName FriendlyName for this KeyStore + * @return Configuration object for {@link EaafKeyStoreFactory} + * @throws EaafConfigurationException In case of a configuration error. + */ + public static KeyStoreConfiguration buildFromConfigurationMap(Map<String, String> config, + String friendlyName) throws EaafConfigurationException { + + final KeyStoreConfiguration internalConfig = new KeyStoreConfiguration(); + internalConfig.setFriendlyName(friendlyName); + + final KeyStoreType internalKeyStoreType = KeyStoreType.fromString( + getConfigurationParameter(config, PROP_CONFIG_KEYSTORE_TYPE)); + if (internalKeyStoreType != null) { + internalConfig.setKeyStoreType(internalKeyStoreType); + + } else { + log.error("KeyStore: {} sets an unknown KeyStore type: {}", + friendlyName, getConfigurationParameter(config, PROP_CONFIG_KEYSTORE_TYPE)); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01, + new Object[] { friendlyName }); + + } + + if (internalKeyStoreType.equals(KeyStoreType.HSMFACADE)) { + log.trace("Set-up HSM-Facade KeyStore ... "); + internalConfig.setKeyStoreName( + getConfigurationParameter(config, PROP_CONFIG_HSMFACADE_NAME)); + + } else if (internalKeyStoreType.equals(KeyStoreType.PKCS12) + || internalKeyStoreType.equals(KeyStoreType.JKS)) { + log.trace("Set-up software KeyStore ... "); + internalConfig.setSoftKeyStoreFilePath( + getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEYSTORE_PATH)); + internalConfig.setSoftKeyStorePassword( + getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEYSTORE_PASSORD)); + + } else { + log.info("Configuration of type: {} not supported yet", internalKeyStoreType); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_02, + new Object[] { friendlyName, config.get(PROP_CONFIG_KEYSTORE_TYPE) }); + + } + + return internalConfig; + } + + /** + * Set the Type of the KeyStore based on String identifier. + * + * @param keyStoreType String based KeyStore type + * @throws EaafConfigurationException In case of an unknown KeyStore type + */ + public void setKeyStoreType(@Nonnull String keyStoreType) throws EaafConfigurationException { + final KeyStoreType internalKeyStoreType = KeyStoreType.fromString(keyStoreType); + if (internalKeyStoreType != null) { + setKeyStoreType(internalKeyStoreType); + + } else { + log.error("KeyStore: {} sets an unknown KeyStore type: {}", + friendlyName, keyStoreType); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01, + new Object[] { friendlyName }); + + } + + } + + /** + * Set the Type of the KeyStore based on String identifier. + * + * @param type String based KeyStore type + */ + public void setKeyStoreType(@Nonnull KeyStoreType type) { + this.keyStoreType = type; + + } + + /** + * Validate the internal state of this configuration object. + * + * @throws EaafConfigurationException In case of a configuration error + */ + public void validate() throws EaafConfigurationException { + if (KeyStoreType.HSMFACADE.equals(keyStoreType)) { + log.trace("Validate HSM-Facade KeyStore ... "); + checkConfigurationValue(keyStoreName, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyName' for HSM-Facade"); + + } else if (KeyStoreType.PKCS12.equals(keyStoreType) + || KeyStoreType.JKS.equals(keyStoreType)) { + log.trace("Validate software KeyStore ... "); + checkConfigurationValue(softKeyStoreFilePath, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyPath' for software keystore"); + checkConfigurationValue(softKeyStorePassword, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyPassword' for software keystore"); + + } else { + log.info("Validation of type: {} not supported yet", keyStoreType); + + } + } + + public enum KeyStoreType { + PKCS12("pkcs12"), JKS("jks"), HSMFACADE("hsmfacade"), PKCS11("pkcs11"); + + private final String keyStoreType; + + KeyStoreType(final String keyStoreType) { + this.keyStoreType = keyStoreType; + } + + /** + * Get Type of this KeyStore. + * + * @return + */ + public String getKeyStoreType() { + return this.keyStoreType; + } + + /** + * Get KeyStore type from String representation. + * + * @param s Config parameter + * @return + */ + public static KeyStoreType fromString(final String s) { + try { + return KeyStoreType.valueOf(s.toUpperCase()); + + } catch (IllegalArgumentException | NullPointerException e) { + return null; + } + } + + @Override + public String toString() { + return getKeyStoreType(); + + } + } + + @Nonnull + private static String getConfigurationParameter(@Nonnull Map<String, String> config, + @Nonnull String configParamKey) + throws EaafConfigurationException { + final String configValue = config.get(configParamKey); + checkConfigurationValue(configValue, EaafKeyStoreFactory.ERRORCODE_04, configParamKey); + return configValue; + + } + + private static void checkConfigurationValue(String configValue, String errorCode, String... params) + throws EaafConfigurationException { + if (StringUtils.isEmpty(configValue)) { + throw new EaafConfigurationException(errorCode, + new Object[] { params}); + + } + + } +} |