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@69: import info.globalcode.sql.dk.formatting.ColumnsHeader; 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@17: import java.io.InputStreamReader; franta-hg@14: import java.io.PrintStream; franta-hg@65: import java.sql.SQLException; franta-hg@70: import java.util.ArrayList; franta-hg@70: import java.util.EnumSet; franta-hg@66: import java.util.List; franta-hg@17: import java.util.logging.Level; 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@17: private PrintStream out; franta-hg@20: private ConfigurationProvider configurationProvider; franta-hg@69: private 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@70: for (InfoType infoType : commands) { franta-hg@70: switch (infoType) { franta-hg@74: // only these need formatted output franta-hg@70: case CONNECTION: franta-hg@70: case DATABASES: franta-hg@70: case FORMATTERS: franta-hg@70: case TYPES: franta-hg@70: formatter = getFormatter(); franta-hg@70: formatter.writeStartDatabase(new DatabaseDefinition()); franta-hg@70: } franta-hg@70: } franta-hg@70: franta-hg@70: for (InfoType infoType : commands) { franta-hg@70: infoType.showInfo(this); franta-hg@70: } franta-hg@70: franta-hg@70: if (formatter != null) { franta-hg@70: formatter.writeEndDatabase(); franta-hg@70: } franta-hg@70: } franta-hg@70: 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@72: new HeaderField("class_name", SQLType.VARCHAR)); 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@72: data.add(new Object[]{fd.getName(), true, defaultFormatter.equals(fd.getName()), fd.getClassName()}); franta-hg@69: } franta-hg@72: franta-hg@72: for (FormatterDefinition fd : configurationProvider.getConfiguration().getFormatters()) { franta-hg@72: data.add(new Object[]{fd.getName(), false, defaultFormatter.equals(fd.getName()), fd.getClassName()}); franta-hg@69: } franta-hg@72: franta-hg@72: printTable(formatter, header, data); franta-hg@72: franta-hg@72: 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@70: printTable(formatter, header, data); 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@72: printTable(formatter, header, data); franta-hg@14: } franta-hg@17: franta-hg@73: public void testConnection() 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: List data = new ArrayList<>(); franta-hg@73: franta-hg@74: for (String dbName : options.getDatabaseNameToTest()) { franta-hg@74: data.add(testConnection(dbName)); franta-hg@74: } franta-hg@73: franta-hg@73: printTable(formatter, header, data); franta-hg@73: } franta-hg@73: 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@75: try (DatabaseConnection dc = dd.connect()) { franta-hg@75: succesfullyConnected = dc.test(); franta-hg@69: } franta-hg@75: log.log(Level.FINE, "Database connection test was successful"); franta-hg@69: } catch (ConfigurationException | SQLException e) { franta-hg@69: log.log(Level.SEVERE, "Error during testing connection", 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@69: private void printTable(Formatter formatter, ColumnsHeader header, List data) throws ConfigurationException, FormatterException { franta-hg@69: formatter.writeStartResultSet(); franta-hg@69: formatter.writeColumnsHeader(header); franta-hg@69: franta-hg@69: for (Object[] row : data) { franta-hg@69: formatter.writeStartRow(); franta-hg@69: for (Object cell : row) { franta-hg@69: formatter.writeColumnValue(cell); franta-hg@69: } franta-hg@69: formatter.writeEndRow(); franta-hg@69: } franta-hg@69: franta-hg@69: formatter.writeEndResultSet(); 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@69: FormatterContext context = new FormatterContext(out); 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@69: @Override franta-hg@69: public void showInfo(InfoLister infoLister) { franta-hg@69: infoLister.printResource(Constants.HELP_FILE); franta-hg@69: } franta-hg@69: }, franta-hg@69: VERSION { franta-hg@69: @Override franta-hg@69: public void showInfo(InfoLister infoLister) { franta-hg@69: infoLister.printResource(Constants.VERSION_FILE); franta-hg@69: } franta-hg@69: }, franta-hg@69: LICENSE { franta-hg@69: @Override franta-hg@69: public void showInfo(InfoLister infoLister) { franta-hg@69: infoLister.printResource(Constants.LICENSE_FILE); franta-hg@69: } franta-hg@69: }, franta-hg@69: FORMATTERS { franta-hg@69: @Override franta-hg@70: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@69: infoLister.listFormatters(); franta-hg@69: } franta-hg@69: }, franta-hg@69: TYPES { franta-hg@69: @Override franta-hg@70: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@69: infoLister.listTypes(); franta-hg@69: } franta-hg@69: }, franta-hg@69: DATABASES { franta-hg@69: @Override franta-hg@70: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@69: infoLister.listDatabases(); franta-hg@69: } franta-hg@69: }, franta-hg@69: CONNECTION { franta-hg@69: @Override franta-hg@73: public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException { franta-hg@69: infoLister.testConnection(); franta-hg@69: } franta-hg@69: }; franta-hg@69: franta-hg@69: public abstract void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException; franta-hg@69: } franta-hg@14: }