001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jdbc.support;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024
025import org.springframework.lang.Nullable;
026
027/**
028 * Registry for custom {@link org.springframework.jdbc.support.SQLExceptionTranslator} instances associated with
029 * specific databases allowing for overriding translation based on values contained in the configuration file
030 * named "sql-error-codes.xml".
031 *
032 * @author Thomas Risberg
033 * @since 3.1.1
034 * @see SQLErrorCodesFactory
035 */
036public final class CustomSQLExceptionTranslatorRegistry {
037
038        private static final Log logger = LogFactory.getLog(CustomSQLExceptionTranslatorRegistry.class);
039
040        /**
041         * Keep track of a single instance so we can return it to classes that request it.
042         */
043        private static final CustomSQLExceptionTranslatorRegistry instance = new CustomSQLExceptionTranslatorRegistry();
044
045
046        /**
047         * Return the singleton instance.
048         */
049        public static CustomSQLExceptionTranslatorRegistry getInstance() {
050                return instance;
051        }
052
053
054        /**
055         * Map registry to hold custom translators specific databases.
056         * Key is the database product name as defined in the
057         * {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
058         */
059        private final Map<String, SQLExceptionTranslator> translatorMap = new HashMap<>();
060
061
062        /**
063         * Create a new instance of the {@link CustomSQLExceptionTranslatorRegistry} class.
064         * <p>Not public to enforce Singleton design pattern.
065         */
066        private CustomSQLExceptionTranslatorRegistry() {
067        }
068
069
070        /**
071         * Register a new custom translator for the specified database name.
072         * @param dbName the database name
073         * @param translator the custom translator
074         */
075        public void registerTranslator(String dbName, SQLExceptionTranslator translator) {
076                SQLExceptionTranslator replaced = this.translatorMap.put(dbName, translator);
077                if (logger.isDebugEnabled()) {
078                        if (replaced != null) {
079                                logger.debug("Replacing custom translator [" + replaced + "] for database '" + dbName +
080                                                "' with [" + translator + "]");
081                        }
082                        else {
083                                logger.debug("Adding custom translator of type [" + translator.getClass().getName() +
084                                                "] for database '" + dbName + "'");
085                        }
086                }
087        }
088
089        /**
090         * Find a custom translator for the specified database.
091         * @param dbName the database name
092         * @return the custom translator, or {@code null} if none found
093         */
094        @Nullable
095        public SQLExceptionTranslator findTranslatorForDatabase(String dbName) {
096                return this.translatorMap.get(dbName);
097        }
098
099}