franta-hg@16: /** franta-hg@16: * SQL-DK franta-hg@16: * Copyright © 2013 František Kučera (frantovo.cz) franta-hg@16: * franta-hg@16: * This program is free software: you can redistribute it and/or modify franta-hg@16: * it under the terms of the GNU General Public License as published by franta-hg@16: * the Free Software Foundation, either version 3 of the License, or franta-hg@16: * (at your option) any later version. franta-hg@16: * franta-hg@16: * This program is distributed in the hope that it will be useful, franta-hg@16: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@16: * GNU General Public License for more details. franta-hg@16: * franta-hg@16: * You should have received a copy of the GNU General Public License franta-hg@16: * along with this program. If not, see . franta-hg@16: */ franta-hg@14: package info.globalcode.sql.dk; franta-hg@14: franta-hg@67: import info.globalcode.sql.dk.configuration.Configuration; franta-hg@65: import info.globalcode.sql.dk.configuration.ConfigurationException; franta-hg@26: import info.globalcode.sql.dk.configuration.ConfigurationProvider; franta-hg@65: import info.globalcode.sql.dk.configuration.DatabaseDefinition; franta-hg@67: import info.globalcode.sql.dk.configuration.FormatterDefinition; franta-hg@160: import info.globalcode.sql.dk.configuration.Properties; franta-hg@159: import info.globalcode.sql.dk.configuration.Property; franta-hg@69: import info.globalcode.sql.dk.formatting.ColumnsHeader; franta-hg@159: import info.globalcode.sql.dk.formatting.FakeSqlArray; franta-hg@69: import info.globalcode.sql.dk.formatting.Formatter; franta-hg@69: import info.globalcode.sql.dk.formatting.FormatterContext; franta-hg@69: import info.globalcode.sql.dk.formatting.FormatterException; franta-hg@17: import java.io.BufferedReader; franta-hg@160: import java.io.ByteArrayOutputStream; franta-hg@17: import java.io.InputStreamReader; franta-hg@14: import java.io.PrintStream; franta-hg@159: import java.sql.Array; franta-hg@158: import java.sql.Driver; franta-hg@196: import java.sql.DriverManager; franta-hg@159: import java.sql.DriverPropertyInfo; franta-hg@65: import java.sql.SQLException; franta-hg@70: import java.util.ArrayList; franta-hg@201: import java.util.Collections; franta-hg@201: import java.util.Comparator; franta-hg@70: import java.util.EnumSet; franta-hg@159: import java.util.HashSet; franta-hg@66: import java.util.List; franta-hg@200: import java.util.Map.Entry; franta-hg@158: import java.util.ServiceLoader; franta-hg@159: import java.util.Set; franta-hg@183: import java.util.concurrent.ExecutorService; franta-hg@183: import java.util.concurrent.Executors; franta-hg@183: import java.util.concurrent.TimeUnit; franta-hg@17: import java.util.logging.Level; franta-hg@196: import java.util.logging.LogRecord; franta-hg@17: import java.util.logging.Logger; franta-hg@69: import javax.sql.rowset.RowSetMetaDataImpl; franta-hg@14: franta-hg@14: /** franta-hg@14: * Displays info like help, version etc. franta-hg@14: * franta-hg@14: * @author Ing. František Kučera (frantovo.cz) franta-hg@14: */ franta-hg@14: public class InfoLister { franta-hg@14: franta-hg@17: private static final Logger log = Logger.getLogger(InfoLister.class.getName()); franta-hg@159: /** franta-hg@159: * Fake database name for output formatting franta-hg@159: */ franta-hg@159: public static final String CONFIG_DB_NAME = "sqldk_configuration"; franta-hg@183: private final PrintStream out; franta-hg@183: private final ConfigurationProvider configurationProvider; franta-hg@183: private final CLIOptions options; franta-hg@70: private Formatter formatter; franta-hg@17: franta-hg@69: public InfoLister(PrintStream out, ConfigurationProvider configurationProvider, CLIOptions options) { franta-hg@17: this.out = out; franta-hg@20: this.configurationProvider = configurationProvider; franta-hg@69: this.options = options; franta-hg@17: } franta-hg@17: franta-hg@70: public void showInfo() throws ConfigurationException, FormatterException { franta-hg@70: EnumSet commands = options.getShowInfo(); franta-hg@70: franta-hg@139: boolean formattinNeeded = false; franta-hg@139: franta-hg@70: for (InfoType infoType : commands) { franta-hg@70: switch (infoType) { franta-hg@70: case CONNECTION: franta-hg@158: case JDBC_DRIVERS: franta-hg@159: case JDBC_PROPERTIES: franta-hg@70: case DATABASES: franta-hg@70: case FORMATTERS: franta-hg@70: case TYPES: franta-hg@200: case JAVA_PROPERTIES: franta-hg@200: case ENVIRONMENT_VARIABLES: franta-hg@139: formattinNeeded = true; franta-hg@101: break; franta-hg@70: } franta-hg@70: } franta-hg@139: franta-hg@139: if (formattinNeeded) { franta-hg@139: try (Formatter f = getFormatter()) { franta-hg@139: formatter = f; franta-hg@139: formatter.writeStartBatch(); franta-hg@159: DatabaseDefinition dd = new DatabaseDefinition(); franta-hg@159: dd.setName(CONFIG_DB_NAME); franta-hg@159: formatter.writeStartDatabase(dd); franta-hg@139: showInfos(commands); franta-hg@139: formatter.writeEndDatabase(); franta-hg@139: formatter.writeEndBatch(); franta-hg@139: formatter.close(); franta-hg@139: } franta-hg@139: } else { franta-hg@139: showInfos(commands); franta-hg@139: } franta-hg@101: } franta-hg@70: franta-hg@101: private void showInfos(EnumSet commands) throws ConfigurationException, FormatterException { franta-hg@70: for (InfoType infoType : commands) { franta-hg@70: infoType.showInfo(this); franta-hg@70: } franta-hg@70: } franta-hg@70: franta-hg@200: private void listJavaProperties() throws FormatterException, ConfigurationException { franta-hg@200: ColumnsHeader header = constructHeader(new HeaderField("name", SQLType.VARCHAR), new HeaderField("value", SQLType.VARCHAR)); franta-hg@200: List data = new ArrayList<>(); franta-hg@200: for (Entry e : System.getProperties().entrySet()) { franta-hg@200: data.add(new Object[]{e.getKey(), e.getValue()}); franta-hg@200: } franta-hg@201: printTable(formatter, header, "-- Java system properties", null, data, 0); franta-hg@200: } franta-hg@200: franta-hg@200: private void listEnvironmentVariables() throws FormatterException, ConfigurationException { franta-hg@200: ColumnsHeader header = constructHeader(new HeaderField("name", SQLType.VARCHAR), new HeaderField("value", SQLType.VARCHAR)); franta-hg@200: List data = new ArrayList<>(); franta-hg@200: for (Entry e : System.getenv().entrySet()) { franta-hg@200: data.add(new Object[]{e.getKey(), e.getValue()}); franta-hg@200: } franta-hg@201: printTable(formatter, header, "-- environment variables", null, data, 0); franta-hg@200: } franta-hg@200: franta-hg@72: private void listFormatters() throws ConfigurationException, FormatterException { franta-hg@72: ColumnsHeader header = constructHeader( franta-hg@72: new HeaderField("name", SQLType.VARCHAR), franta-hg@72: new HeaderField("built_in", SQLType.BOOLEAN), franta-hg@72: new HeaderField("default", SQLType.BOOLEAN), franta-hg@160: new HeaderField("class_name", SQLType.VARCHAR), franta-hg@160: new HeaderField("valid", SQLType.BOOLEAN)); franta-hg@72: List data = new ArrayList<>(); franta-hg@72: franta-hg@72: String defaultFormatter = configurationProvider.getConfiguration().getDefaultFormatter(); franta-hg@72: defaultFormatter = defaultFormatter == null ? Configuration.DEFAULT_FORMATTER : defaultFormatter; franta-hg@72: franta-hg@69: for (FormatterDefinition fd : configurationProvider.getConfiguration().getBuildInFormatters()) { franta-hg@160: data.add(new Object[]{fd.getName(), true, defaultFormatter.equals(fd.getName()), fd.getClassName(), isInstantiable(fd)}); franta-hg@69: } franta-hg@72: franta-hg@72: for (FormatterDefinition fd : configurationProvider.getConfiguration().getFormatters()) { franta-hg@160: data.add(new Object[]{fd.getName(), false, defaultFormatter.equals(fd.getName()), fd.getClassName(), isInstantiable(fd)}); franta-hg@69: } franta-hg@72: franta-hg@183: printTable(formatter, header, "-- configured and built-in output formatters", null, data); franta-hg@160: } franta-hg@72: franta-hg@160: private boolean isInstantiable(FormatterDefinition fd) { franta-hg@160: try { franta-hg@160: try (ByteArrayOutputStream testStream = new ByteArrayOutputStream()) { franta-hg@160: fd.getInstance(new FormatterContext(testStream, new Properties(0))); franta-hg@160: return true; franta-hg@160: } franta-hg@160: } catch (Exception e) { franta-hg@160: log.log(Level.SEVERE, "Unable to create an instance of formatter: " + fd.getName(), e); franta-hg@160: return false; franta-hg@160: } franta-hg@69: } franta-hg@67: franta-hg@70: public void listTypes() throws FormatterException, ConfigurationException { franta-hg@70: ColumnsHeader header = constructHeader(new HeaderField("name", SQLType.VARCHAR), new HeaderField("code", SQLType.INTEGER)); franta-hg@70: List data = new ArrayList<>(); franta-hg@70: for (SQLType sqlType : SQLType.values()) { franta-hg@70: data.add(new Object[]{sqlType.name(), sqlType.getCode()}); franta-hg@70: } franta-hg@183: printTable(formatter, header, "-- data types", null, data); franta-hg@93: log.log(Level.INFO, "Type names in --types option are case insensitive"); franta-hg@69: } franta-hg@67: franta-hg@72: public void listDatabases() throws ConfigurationException, FormatterException { franta-hg@72: ColumnsHeader header = constructHeader( franta-hg@72: new HeaderField("database_name", SQLType.VARCHAR), franta-hg@72: new HeaderField("user_name", SQLType.VARCHAR), franta-hg@72: new HeaderField("database_url", SQLType.VARCHAR)); franta-hg@72: List data = new ArrayList<>(); franta-hg@72: franta-hg@69: final List configuredDatabases = configurationProvider.getConfiguration().getDatabases(); franta-hg@69: if (configuredDatabases.isEmpty()) { franta-hg@69: log.log(Level.WARNING, "No databases are configured."); franta-hg@69: } else { franta-hg@69: for (DatabaseDefinition dd : configuredDatabases) { franta-hg@72: data.add(new Object[]{dd.getName(), dd.getUserName(), dd.getUrl()}); franta-hg@14: } franta-hg@14: } franta-hg@72: franta-hg@183: printTable(formatter, header, "-- configured databases", null, data); franta-hg@14: } franta-hg@17: franta-hg@158: public void listJdbcDrivers() throws FormatterException, ConfigurationException { franta-hg@158: ColumnsHeader header = constructHeader( franta-hg@158: new HeaderField("class", SQLType.VARCHAR), franta-hg@158: new HeaderField("version", SQLType.VARCHAR), franta-hg@158: new HeaderField("major", SQLType.INTEGER), franta-hg@158: new HeaderField("minor", SQLType.INTEGER), franta-hg@158: new HeaderField("jdbc_compliant", SQLType.BOOLEAN)); franta-hg@158: List data = new ArrayList<>(); franta-hg@158: franta-hg@158: final ServiceLoader drivers = ServiceLoader.load(Driver.class); franta-hg@158: for (Driver d : drivers) { franta-hg@158: data.add(new Object[]{ franta-hg@158: d.getClass().getName(), franta-hg@158: d.getMajorVersion() + "." + d.getMinorVersion(), franta-hg@158: d.getMajorVersion(), franta-hg@158: d.getMinorVersion(), franta-hg@159: d.jdbcCompliant() franta-hg@159: }); franta-hg@158: } franta-hg@158: franta-hg@183: printTable(formatter, header, "-- discovered JDBC drivers (available on the CLASSPATH)", null, data); franta-hg@159: } franta-hg@158: franta-hg@159: public void listJdbcProperties() throws FormatterException, ConfigurationException { franta-hg@159: for (String dbName : options.getDatabaseNamesToListProperties()) { franta-hg@159: ColumnsHeader header = constructHeader( franta-hg@159: new HeaderField("property_name", SQLType.VARCHAR), franta-hg@159: new HeaderField("required", SQLType.BOOLEAN), franta-hg@159: new HeaderField("choices", SQLType.ARRAY), franta-hg@159: new HeaderField("configured_value", SQLType.VARCHAR), franta-hg@159: new HeaderField("description", SQLType.VARCHAR)); franta-hg@159: List data = new ArrayList<>(); franta-hg@159: franta-hg@159: DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName); franta-hg@159: franta-hg@159: Driver driver = findDriver(dd); franta-hg@159: franta-hg@159: if (driver == null) { franta-hg@159: log.log(Level.WARNING, "No JDBC driver was found for DB: {0} with URL: {1}", new Object[]{dd.getName(), dd.getUrl()}); franta-hg@159: } else { franta-hg@159: log.log(Level.INFO, "For DB: {0} was found JDBC driver: {1}", new Object[]{dd.getName(), driver.getClass().getName()}); franta-hg@159: franta-hg@159: try { franta-hg@159: DriverPropertyInfo[] propertyInfos = driver.getPropertyInfo(dd.getUrl(), dd.getProperties().getJavaProperties()); franta-hg@159: franta-hg@159: Set standardProperties = new HashSet<>(); franta-hg@159: franta-hg@159: for (DriverPropertyInfo pi : propertyInfos) { franta-hg@159: Array choices = new FakeSqlArray(pi.choices, SQLType.VARCHAR); franta-hg@159: data.add(new Object[]{ franta-hg@159: pi.name, franta-hg@159: pi.required, franta-hg@159: choices.getArray() == null ? "" : choices, franta-hg@159: pi.value == null ? "" : pi.value, franta-hg@159: pi.description franta-hg@159: }); franta-hg@159: standardProperties.add(pi.name); franta-hg@159: } franta-hg@159: franta-hg@159: for (Property p : dd.getProperties()) { franta-hg@159: if (!standardProperties.contains(p.getName())) { franta-hg@159: data.add(new Object[]{ franta-hg@159: p.getName(), franta-hg@159: "", franta-hg@159: "", franta-hg@159: p.getValue(), franta-hg@159: "" franta-hg@159: }); franta-hg@159: log.log(Level.WARNING, "Your configuration contains property „{0}“ not declared by the JDBC driver.", p.getName()); franta-hg@159: } franta-hg@159: } franta-hg@159: franta-hg@159: } catch (SQLException e) { franta-hg@159: log.log(Level.WARNING, "Error during getting property infos.", e); franta-hg@159: } franta-hg@159: franta-hg@159: List parameters = new ArrayList<>(); franta-hg@197: parameters.add(new NamedParameter("database", dbName, SQLType.VARCHAR)); franta-hg@159: parameters.add(new NamedParameter("driver_class", driver.getClass().getName(), SQLType.VARCHAR)); franta-hg@159: parameters.add(new NamedParameter("driver_major_version", driver.getMajorVersion(), SQLType.INTEGER)); franta-hg@159: parameters.add(new NamedParameter("driver_minor_version", driver.getMinorVersion(), SQLType.INTEGER)); franta-hg@159: franta-hg@183: printTable(formatter, header, "-- configured and configurable JDBC driver properties", parameters, data); franta-hg@159: } franta-hg@159: } franta-hg@159: franta-hg@159: } franta-hg@159: franta-hg@159: private Driver findDriver(DatabaseDefinition dd) { franta-hg@159: final ServiceLoader drivers = ServiceLoader.load(Driver.class); franta-hg@159: for (Driver d : drivers) { franta-hg@159: try { franta-hg@159: if (d.acceptsURL(dd.getUrl())) { franta-hg@159: return d; franta-hg@159: } franta-hg@159: } catch (SQLException e) { franta-hg@159: log.log(Level.WARNING, "Error during finding JDBC driver for: " + dd.getName(), e); franta-hg@159: } franta-hg@159: } franta-hg@159: return null; franta-hg@158: } franta-hg@158: franta-hg@183: /** franta-hg@183: * Parallelism for connection testing – maximum concurrent database connections. franta-hg@183: */ franta-hg@183: private static final int TESTING_THREAD_COUNT = 64; franta-hg@183: /** franta-hg@183: * Time limit for all connection testing threads – particular timeouts per connection will be franta-hg@183: * much smaller. franta-hg@183: */ franta-hg@183: private static final long TESTING_AWAIT_LIMIT = 1; franta-hg@183: private static final TimeUnit TESTING_AWAIT_UNIT = TimeUnit.DAYS; franta-hg@183: franta-hg@183: public void testConnections() throws FormatterException, ConfigurationException { franta-hg@73: ColumnsHeader header = constructHeader( franta-hg@73: new HeaderField("database_name", SQLType.VARCHAR), franta-hg@74: new HeaderField("configured", SQLType.BOOLEAN), franta-hg@74: new HeaderField("connected", SQLType.BOOLEAN)); franta-hg@73: franta-hg@183: log.log(Level.FINE, "Testing DB connections in {0} threads", TESTING_THREAD_COUNT); franta-hg@183: franta-hg@183: ExecutorService es = Executors.newFixedThreadPool(TESTING_THREAD_COUNT); franta-hg@183: franta-hg@183: final Formatter currentFormatter = formatter; franta-hg@183: franta-hg@183: printHeader(currentFormatter, header, "-- database configuration and connectivity test", null); franta-hg@183: franta-hg@183: for (final String dbName : options.getDatabaseNamesToTest()) { franta-hg@196: preloadDriver(dbName); franta-hg@196: } franta-hg@196: franta-hg@196: for (final String dbName : options.getDatabaseNamesToTest()) { franta-hg@183: es.submit(new Runnable() { franta-hg@183: // TODO: Java 8 – lambda franta-hg@183: @Override franta-hg@183: public void run() { franta-hg@183: final Object[] row = testConnection(dbName); franta-hg@183: synchronized (currentFormatter) { franta-hg@183: printRow(currentFormatter, row); franta-hg@183: } franta-hg@183: } franta-hg@183: }); franta-hg@74: } franta-hg@73: franta-hg@183: es.shutdown(); franta-hg@183: franta-hg@183: try { franta-hg@183: log.log(Level.FINEST, "Waiting for test results: {0} {1}", new Object[]{TESTING_AWAIT_LIMIT, TESTING_AWAIT_UNIT.name()}); franta-hg@183: boolean finished = es.awaitTermination(TESTING_AWAIT_LIMIT, TESTING_AWAIT_UNIT); franta-hg@183: if (finished) { franta-hg@183: log.log(Level.FINEST, "All testing threads finished in time limit."); franta-hg@183: } else { franta-hg@183: throw new FormatterException("Exceeded total time limit for test threads – this should never happen"); franta-hg@183: } franta-hg@183: } catch (InterruptedException e) { franta-hg@183: throw new FormatterException("Interrupted while waiting for test results", e); franta-hg@183: } franta-hg@183: franta-hg@183: printFooter(currentFormatter); franta-hg@73: } franta-hg@73: franta-hg@196: /** franta-hg@196: * JDBC driver classes should be preloaded in single thread to avoid deadlocks while doing franta-hg@196: * {@linkplain DriverManager#registerDriver(java.sql.Driver)} during parallel connections. franta-hg@196: * franta-hg@196: * @param dbName franta-hg@196: */ franta-hg@196: private void preloadDriver(String dbName) { franta-hg@196: try { franta-hg@196: DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName); franta-hg@196: Driver driver = findDriver(dd); franta-hg@196: if (driver == null) { franta-hg@196: log.log(Level.WARNING, "No Driver found for DB: {0}", dbName); franta-hg@196: } else { franta-hg@196: log.log(Level.FINEST, "Driver preloading for DB: {0} was successfull", dbName); franta-hg@196: } franta-hg@196: } catch (Exception e) { franta-hg@196: LogRecord r = new LogRecord(Level.WARNING, "Failed to preload the Driver for DB: {0}"); franta-hg@196: r.setParameters(new Object[]{dbName}); franta-hg@196: r.setThrown(e); franta-hg@196: log.log(r); franta-hg@196: } franta-hg@196: } franta-hg@196: franta-hg@73: public Object[] testConnection(String dbName) { franta-hg@69: log.log(Level.FINE, "Testing connection to database: {0}", dbName); franta-hg@73: franta-hg@73: boolean succesfullyConnected = false; franta-hg@73: boolean succesfullyConfigured = false; franta-hg@73: franta-hg@69: try { franta-hg@69: DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName); franta-hg@75: log.log(Level.FINE, "Database definition was loaded from configuration"); franta-hg@75: succesfullyConfigured = true; franta-hg@106: try (DatabaseConnection dc = dd.connect(options.getDatabaseProperties())) { franta-hg@75: succesfullyConnected = dc.test(); franta-hg@69: } franta-hg@75: log.log(Level.FINE, "Database connection test was successful"); franta-hg@196: } catch (ConfigurationException | SQLException | RuntimeException e) { franta-hg@183: log.log(Level.SEVERE, "Error during testing connection " + dbName, e); franta-hg@69: } franta-hg@73: franta-hg@73: return new Object[]{dbName, succesfullyConfigured, succesfullyConnected}; franta-hg@69: } franta-hg@69: franta-hg@69: public void printResource(String fileName) { franta-hg@18: try (BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream(fileName)))) { franta-hg@17: while (true) { franta-hg@18: String line = reader.readLine(); franta-hg@17: if (line == null) { franta-hg@17: break; franta-hg@17: } else { franta-hg@17: println(line); franta-hg@17: } franta-hg@17: } franta-hg@17: } catch (Exception e) { franta-hg@18: log.log(Level.SEVERE, "Unable to print this info. Please see our website for it: " + Constants.WEBSITE, e); franta-hg@17: } franta-hg@17: } franta-hg@17: franta-hg@17: private void println(String line) { franta-hg@17: out.println(line); franta-hg@17: } franta-hg@69: franta-hg@183: private void printTable(Formatter formatter, ColumnsHeader header, String sql, List parameters, List data) throws ConfigurationException, FormatterException { franta-hg@201: printTable(formatter, header, sql, parameters, data, null); franta-hg@201: } franta-hg@201: franta-hg@201: private void printTable(Formatter formatter, ColumnsHeader header, String sql, List parameters, List data, final Integer sortByColumn) throws ConfigurationException, FormatterException { franta-hg@183: printHeader(formatter, header, sql, parameters); franta-hg@183: franta-hg@201: if (sortByColumn != null) { franta-hg@201: Collections.sort(data, new Comparator() { franta-hg@201: franta-hg@201: @Override franta-hg@201: public int compare(Object[] o1, Object[] o2) { franta-hg@201: String s1 = String.valueOf(o1[sortByColumn]); franta-hg@201: String s2 = String.valueOf(o2[sortByColumn]); franta-hg@201: return s1.compareTo(s2); franta-hg@201: } franta-hg@201: }); franta-hg@201: } franta-hg@201: franta-hg@183: for (Object[] row : data) { franta-hg@183: printRow(formatter, row); franta-hg@183: } franta-hg@183: franta-hg@183: printFooter(formatter); franta-hg@183: } franta-hg@183: franta-hg@183: private void printHeader(Formatter formatter, ColumnsHeader header, String sql, List parameters) { franta-hg@159: formatter.writeStartStatement(); franta-hg@159: if (sql != null) { franta-hg@159: formatter.writeQuery(sql); franta-hg@159: if (parameters != null) { franta-hg@159: formatter.writeParameters(parameters); franta-hg@159: } franta-hg@159: } franta-hg@183: formatter.writeStartResultSet(header); franta-hg@183: } franta-hg@159: franta-hg@183: private void printRow(Formatter formatter, Object[] row) { franta-hg@183: formatter.writeStartRow(); franta-hg@183: for (Object cell : row) { franta-hg@183: formatter.writeColumnValue(cell); franta-hg@183: } franta-hg@183: formatter.writeEndRow(); franta-hg@183: } franta-hg@69: franta-hg@183: private void printFooter(Formatter formatter) { franta-hg@69: formatter.writeEndResultSet(); franta-hg@159: formatter.writeEndStatement(); franta-hg@69: } franta-hg@69: franta-hg@69: private Formatter getFormatter() throws ConfigurationException, FormatterException { franta-hg@89: String formatterName = options.getFormatterName(); franta-hg@89: formatterName = formatterName == null ? Configuration.DEFAULT_FORMATTER_PREFETCHING : formatterName; franta-hg@89: FormatterDefinition fd = configurationProvider.getConfiguration().getFormatter(formatterName); franta-hg@104: FormatterContext context = new FormatterContext(out, options.getFormatterProperties()); franta-hg@69: return fd.getInstance(context); franta-hg@69: } franta-hg@69: franta-hg@69: private ColumnsHeader constructHeader(HeaderField... fields) throws FormatterException { franta-hg@69: try { franta-hg@69: RowSetMetaDataImpl metaData = new RowSetMetaDataImpl(); franta-hg@69: metaData.setColumnCount(fields.length); franta-hg@69: franta-hg@69: for (int i = 0; i < fields.length; i++) { franta-hg@69: HeaderField hf = fields[i]; franta-hg@69: int sqlIndex = i + 1; franta-hg@69: metaData.setColumnName(sqlIndex, hf.name); franta-hg@69: metaData.setColumnLabel(sqlIndex, hf.name); franta-hg@69: metaData.setColumnType(sqlIndex, hf.type.getCode()); franta-hg@69: metaData.setColumnTypeName(sqlIndex, hf.type.name()); franta-hg@69: } franta-hg@69: franta-hg@69: return new ColumnsHeader(metaData); franta-hg@69: } catch (SQLException e) { franta-hg@69: throw new FormatterException("Error while constructing table headers", e); franta-hg@69: } franta-hg@69: } franta-hg@69: franta-hg@69: private static class HeaderField { franta-hg@69: franta-hg@69: String name; franta-hg@69: SQLType type; franta-hg@69: franta-hg@69: public HeaderField(String name, SQLType type) { franta-hg@69: this.name = name; franta-hg@69: this.type = type; franta-hg@69: } franta-hg@69: } franta-hg@69: franta-hg@69: public enum InfoType { franta-hg@69: franta-hg@69: HELP { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) { franta-hg@183: infoLister.printResource(Constants.HELP_FILE); franta-hg@183: } franta-hg@183: }, franta-hg@69: VERSION { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) { franta-hg@183: infoLister.printResource(Constants.VERSION_FILE); franta-hg@183: } franta-hg@183: }, franta-hg@69: LICENSE { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) { franta-hg@183: infoLister.printResource(Constants.LICENSE_FILE); franta-hg@183: } franta-hg@183: }, franta-hg@200: JAVA_PROPERTIES { franta-hg@200: @Override franta-hg@200: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@200: infoLister.listJavaProperties(); franta-hg@200: } franta-hg@200: }, franta-hg@200: ENVIRONMENT_VARIABLES { franta-hg@200: @Override franta-hg@200: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@200: infoLister.listEnvironmentVariables(); franta-hg@200: } franta-hg@200: }, franta-hg@69: FORMATTERS { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@183: infoLister.listFormatters(); franta-hg@183: } franta-hg@183: }, franta-hg@69: TYPES { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@183: infoLister.listTypes(); franta-hg@183: } franta-hg@183: }, franta-hg@158: JDBC_DRIVERS { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException { franta-hg@183: infoLister.listJdbcDrivers(); franta-hg@183: } franta-hg@183: }, franta-hg@159: JDBC_PROPERTIES { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException { franta-hg@183: infoLister.listJdbcProperties(); franta-hg@183: } franta-hg@183: }, franta-hg@69: DATABASES { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@183: infoLister.listDatabases(); franta-hg@183: } franta-hg@183: }, franta-hg@69: CONNECTION { franta-hg@183: @Override franta-hg@183: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@183: infoLister.testConnections(); franta-hg@183: } franta-hg@183: }; franta-hg@69: franta-hg@69: public abstract void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException; franta-hg@69: } franta-hg@14: }