001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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 * http://www.opensource.org/licenses/ecl2.php
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 */
016package org.kuali.rice.krad.data.platform;
017
018import org.springframework.dao.DataAccessException;
019import org.springframework.jdbc.core.ConnectionCallback;
020import org.springframework.jdbc.core.JdbcTemplate;
021
022import javax.sql.DataSource;
023import java.sql.Connection;
024import java.sql.DatabaseMetaData;
025import java.sql.SQLException;
026import java.util.Collections;
027import java.util.IdentityHashMap;
028import java.util.Map;
029import java.util.concurrent.ConcurrentHashMap;
030import java.util.concurrent.ConcurrentMap;
031
032/**
033 * Contains constants and utilities related to the supported database platforms.
034 *
035 * <p>
036 * We use a String to represent the platform name as opposed to an Enum because this allows for the potential to
037 * configure and use custom platforms at runtime without requiring internal code modification to support a new platform.
038 * </p>
039 *
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042public final class DatabasePlatforms {
043
044    /**
045     * The name of the Oracle platform.
046     */
047    public static final String ORACLE = "Oracle";
048
049    /**
050     * The name of the MySQL platform.
051     */
052    public static final String MYSQL = "MySQL";
053
054    private static final Map<DataSource, DatabasePlatformInfo> platformCache
055            = Collections.synchronizedMap(new IdentityHashMap<DataSource, DatabasePlatformInfo>(8));
056
057    /**
058     * Gets the platform information from the {@link DataSource}.
059     *
060     * @param dataSource the {@link DataSource} to consult.
061     * @return the platform information from the {@link DataSource}.
062     */
063    public static DatabasePlatformInfo detectPlatform(DataSource dataSource) {
064        if (dataSource == null) {
065            throw new IllegalArgumentException("DataSource must not be null.");
066        }
067        DatabasePlatformInfo platformInfo = platformCache.get(dataSource);
068        if (platformInfo == null) {
069            JdbcTemplate template = new JdbcTemplate(dataSource);
070                platformCache.put(dataSource, template.execute(new ConnectionCallback<DatabasePlatformInfo>() {
071                            @Override
072                            public DatabasePlatformInfo doInConnection(
073                                    Connection connection) throws SQLException, DataAccessException {
074                                DatabaseMetaData metadata = connection.getMetaData();
075                                String vendorName = metadata.getDatabaseProductName();
076                                int version = metadata.getDatabaseMajorVersion();
077                                return new DatabasePlatformInfo(vendorName, version);
078                            }
079                    }));
080            if (platformInfo == null) {
081                platformInfo = platformCache.get(dataSource);
082            }
083        }
084        return platformInfo;
085    }
086
087    /**
088     * No-op constructor for final class.
089     */
090    private DatabasePlatforms() {}
091
092}