001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.dao.db;
016    
017    import com.liferay.portal.dao.orm.hibernate.DialectImpl;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactory;
020    import com.liferay.portal.kernel.dao.db.DBManager;
021    import com.liferay.portal.kernel.dao.db.DBType;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025    import com.liferay.portal.kernel.util.InfrastructureUtil;
026    import com.liferay.portal.kernel.util.InstanceFactory;
027    import com.liferay.portal.kernel.util.ReflectionUtil;
028    import com.liferay.portal.util.PropsValues;
029    
030    import java.sql.Connection;
031    import java.sql.DatabaseMetaData;
032    import java.sql.SQLException;
033    
034    import java.util.EnumMap;
035    import java.util.ServiceLoader;
036    
037    import javax.sql.DataSource;
038    
039    import org.hibernate.dialect.DB2Dialect;
040    import org.hibernate.dialect.Dialect;
041    import org.hibernate.dialect.HSQLDialect;
042    import org.hibernate.dialect.MySQLDialect;
043    import org.hibernate.dialect.Oracle8iDialect;
044    import org.hibernate.dialect.Oracle9Dialect;
045    import org.hibernate.dialect.PostgreSQLDialect;
046    import org.hibernate.dialect.SQLServerDialect;
047    import org.hibernate.dialect.Sybase11Dialect;
048    import org.hibernate.dialect.SybaseASE15Dialect;
049    import org.hibernate.dialect.SybaseAnywhereDialect;
050    import org.hibernate.dialect.SybaseDialect;
051    
052    /**
053     * @author Alexander Chow
054     * @author Brian Wing Shun Chan
055     */
056    @DoPrivileged
057    @SuppressWarnings("deprecation")
058    public class DBManagerImpl implements DBManager {
059    
060            public DBManagerImpl() {
061                    ServiceLoader<DBFactory> serviceLoader = ServiceLoader.load(
062                            DBFactory.class, DBManagerImpl.class.getClassLoader());
063    
064                    for (DBFactory dbFactory : serviceLoader) {
065                            _dbFactories.put(dbFactory.getDBType(), dbFactory);
066                    }
067            }
068    
069            @Override
070            public DB getDB() {
071                    if (_db == null) {
072                            try {
073                                    if (_log.isInfoEnabled()) {
074                                            _log.info("Using dialect " + PropsValues.HIBERNATE_DIALECT);
075                                    }
076    
077                                    Dialect dialect = (Dialect)InstanceFactory.newInstance(
078                                            PropsValues.HIBERNATE_DIALECT);
079    
080                                    setDB(
081                                            getDB(
082                                                    getDBType(dialect),
083                                                    InfrastructureUtil.getDataSource()));
084                            }
085                            catch (Exception e) {
086                                    _log.error(e, e);
087                            }
088                    }
089    
090                    return _db;
091            }
092    
093            @Override
094            public DB getDB(DBType dbType, DataSource dataSource) {
095                    int dbMajorVersion = 0;
096                    int dbMinorVersion = 0;
097    
098                    if (dataSource != null) {
099                            try (Connection connection = dataSource.getConnection()) {
100                                    DatabaseMetaData databaseMetaData = connection.getMetaData();
101    
102                                    dbMajorVersion = databaseMetaData.getDatabaseMajorVersion();
103                                    dbMinorVersion = databaseMetaData.getDatabaseMinorVersion();
104                            }
105                            catch (SQLException sqle) {
106                                    return ReflectionUtil.throwException(sqle);
107                            }
108                    }
109    
110                    DBFactory dbCreator = _dbFactories.get(dbType);
111    
112                    if (dbCreator == null) {
113                            throw new IllegalArgumentException(
114                                    "Unsupported database type " + dbType);
115                    }
116    
117                    return dbCreator.create(dbMajorVersion, dbMinorVersion);
118            }
119    
120            @Override
121            public DBType getDBType(Object dialect) {
122                    if (dialect instanceof DialectImpl) {
123                            DialectImpl dialectImpl = (DialectImpl)dialect;
124    
125                            dialect = dialectImpl.getWrappedDialect();
126                    }
127    
128                    if (dialect instanceof DB2Dialect) {
129                            return DBType.DB2;
130                    }
131    
132                    if (dialect instanceof HSQLDialect) {
133                            return DBType.HYPERSONIC;
134                    }
135    
136                    if (dialect instanceof MySQLDialect) {
137                            return DBType.MYSQL;
138                    }
139    
140                    if (dialect instanceof Oracle8iDialect ||
141                            dialect instanceof Oracle9Dialect) {
142    
143                            return DBType.ORACLE;
144                    }
145    
146                    if (dialect instanceof PostgreSQLDialect) {
147                            return DBType.POSTGRESQL;
148                    }
149    
150                    if (dialect instanceof SQLServerDialect) {
151                            return DBType.SQLSERVER;
152                    }
153    
154                    if (dialect instanceof SybaseDialect ||
155                            dialect instanceof Sybase11Dialect ||
156                            dialect instanceof SybaseAnywhereDialect ||
157                            dialect instanceof SybaseASE15Dialect) {
158    
159                            return DBType.SYBASE;
160                    }
161    
162                    throw new IllegalArgumentException("Unknown dialect type " + dialect);
163            }
164    
165            @Override
166            public void setDB(DB db) {
167                    _db = db;
168    
169                    if (_log.isDebugEnabled()) {
170                            Class<?> clazz = _db.getClass();
171    
172                            _log.debug(
173                                    "Using DB implementation " + clazz.getName() + " for " +
174                                            db.getDBType());
175                    }
176            }
177    
178            private static final Log _log = LogFactoryUtil.getLog(DBManagerImpl.class);
179    
180            private DB _db;
181            private final EnumMap<DBType, DBFactory> _dbFactories = new EnumMap<>(
182                    DBType.class);
183    
184    }