/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.console.agent.db; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.ignite.console.agent.db.dialect.DB2MetadataDialect; import org.apache.ignite.console.agent.db.dialect.DatabaseMetadataDialect; import org.apache.ignite.console.agent.db.dialect.JdbcMetadataDialect; import org.apache.ignite.console.agent.db.dialect.MySQLMetadataDialect; import org.apache.ignite.console.agent.db.dialect.OracleMetadataDialect; import org.apache.log4j.Logger; /** * Singleton to extract database metadata. */ public class DbMetadataReader { /** Logger. */ private static final Logger log = Logger.getLogger(DbMetadataReader.class.getName()); /** */ private final Map<String, Driver> drivers = new HashMap<>(); /** * Get specified dialect object for selected database. * * @param conn Connection to database. * @return Specific dialect object. */ private DatabaseMetadataDialect dialect(Connection conn) { try { String dbProductName = conn.getMetaData().getDatabaseProductName(); if ("Oracle".equals(dbProductName)) return new OracleMetadataDialect(); if (dbProductName.startsWith("DB2/")) return new DB2MetadataDialect(); if ("MySQL".equals(dbProductName)) return new MySQLMetadataDialect(); return new JdbcMetadataDialect(); } catch (SQLException e) { log.error("Failed to resolve dialect (JdbcMetaDataDialect will be used.", e); return new JdbcMetadataDialect(); } } /** * Get list of schemas from database. * * @param conn Connection to database. * @return List of schema names. * @throws SQLException If schemas loading failed. */ public Collection<String> schemas(Connection conn) throws SQLException { return dialect(conn).schemas(conn); } /** * Extract DB metadata. * * @param conn Connection. * @param schemas List of database schemas to process. In case of empty list all schemas will be processed. * @param tblsOnly Tables only flag. */ public Collection<DbTable> metadata(Connection conn, List<String> schemas, boolean tblsOnly) throws SQLException { return dialect(conn).tables(conn, schemas, tblsOnly); } /** * Connect to database. * * @param jdbcDrvJarPath Path to JDBC driver. * @param jdbcDrvCls JDBC class name. * @param jdbcUrl JDBC connection URL. * @param jdbcInfo Connection properties. * @return Connection to database. * @throws SQLException if connection failed. */ public Connection connect(String jdbcDrvJarPath, String jdbcDrvCls, String jdbcUrl, Properties jdbcInfo) throws SQLException { Driver drv = drivers.get(jdbcDrvCls); if (drv == null) { if (jdbcDrvJarPath.isEmpty()) throw new IllegalStateException("Driver jar file name is not specified."); File drvJar = new File(jdbcDrvJarPath); if (!drvJar.exists()) throw new IllegalStateException("Driver jar file is not found."); try { URL u = new URL("jar:" + drvJar.toURI() + "!/"); URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {u}); drv = (Driver)Class.forName(jdbcDrvCls, true, ucl).newInstance(); drivers.put(jdbcDrvCls, drv); } catch (Exception e) { throw new IllegalStateException(e); } } Connection conn = drv.connect(jdbcUrl, jdbcInfo); if (conn == null) throw new IllegalStateException("Connection was not established (JDBC driver returned null value)."); return conn; } }