java/sql-dk/src/info/globalcode/sql/dk/InfoLister.java
branchv_0
changeset 159 9632b23df30c
parent 158 770b5009ec42
child 160 84ea4a819fb2
equal deleted inserted replaced
158:770b5009ec42 159:9632b23df30c
    20 import info.globalcode.sql.dk.configuration.Configuration;
    20 import info.globalcode.sql.dk.configuration.Configuration;
    21 import info.globalcode.sql.dk.configuration.ConfigurationException;
    21 import info.globalcode.sql.dk.configuration.ConfigurationException;
    22 import info.globalcode.sql.dk.configuration.ConfigurationProvider;
    22 import info.globalcode.sql.dk.configuration.ConfigurationProvider;
    23 import info.globalcode.sql.dk.configuration.DatabaseDefinition;
    23 import info.globalcode.sql.dk.configuration.DatabaseDefinition;
    24 import info.globalcode.sql.dk.configuration.FormatterDefinition;
    24 import info.globalcode.sql.dk.configuration.FormatterDefinition;
       
    25 import info.globalcode.sql.dk.configuration.Property;
    25 import info.globalcode.sql.dk.formatting.ColumnsHeader;
    26 import info.globalcode.sql.dk.formatting.ColumnsHeader;
       
    27 import info.globalcode.sql.dk.formatting.FakeSqlArray;
    26 import info.globalcode.sql.dk.formatting.Formatter;
    28 import info.globalcode.sql.dk.formatting.Formatter;
    27 import info.globalcode.sql.dk.formatting.FormatterContext;
    29 import info.globalcode.sql.dk.formatting.FormatterContext;
    28 import info.globalcode.sql.dk.formatting.FormatterException;
    30 import info.globalcode.sql.dk.formatting.FormatterException;
    29 import java.io.BufferedReader;
    31 import java.io.BufferedReader;
    30 import java.io.InputStreamReader;
    32 import java.io.InputStreamReader;
    31 import java.io.PrintStream;
    33 import java.io.PrintStream;
       
    34 import java.sql.Array;
    32 import java.sql.Driver;
    35 import java.sql.Driver;
       
    36 import java.sql.DriverPropertyInfo;
    33 import java.sql.SQLException;
    37 import java.sql.SQLException;
    34 import java.util.ArrayList;
    38 import java.util.ArrayList;
    35 import java.util.EnumSet;
    39 import java.util.EnumSet;
       
    40 import java.util.HashSet;
    36 import java.util.List;
    41 import java.util.List;
    37 import java.util.ServiceLoader;
    42 import java.util.ServiceLoader;
       
    43 import java.util.Set;
    38 import java.util.logging.Level;
    44 import java.util.logging.Level;
    39 import java.util.logging.Logger;
    45 import java.util.logging.Logger;
    40 import javax.sql.rowset.RowSetMetaDataImpl;
    46 import javax.sql.rowset.RowSetMetaDataImpl;
    41 
    47 
    42 /**
    48 /**
    45  * @author Ing. František Kučera (frantovo.cz)
    51  * @author Ing. František Kučera (frantovo.cz)
    46  */
    52  */
    47 public class InfoLister {
    53 public class InfoLister {
    48 
    54 
    49 	private static final Logger log = Logger.getLogger(InfoLister.class.getName());
    55 	private static final Logger log = Logger.getLogger(InfoLister.class.getName());
       
    56 	/**
       
    57 	 * Fake database name for output formatting
       
    58 	 */
       
    59 	public static final String CONFIG_DB_NAME = "sqldk_configuration";
    50 	private PrintStream out;
    60 	private PrintStream out;
    51 	private ConfigurationProvider configurationProvider;
    61 	private ConfigurationProvider configurationProvider;
    52 	private CLIOptions options;
    62 	private CLIOptions options;
    53 	private Formatter formatter;
    63 	private Formatter formatter;
    54 
    64 
    65 
    75 
    66 		for (InfoType infoType : commands) {
    76 		for (InfoType infoType : commands) {
    67 			switch (infoType) {
    77 			switch (infoType) {
    68 				case CONNECTION:
    78 				case CONNECTION:
    69 				case JDBC_DRIVERS:
    79 				case JDBC_DRIVERS:
       
    80 				case JDBC_PROPERTIES:
    70 				case DATABASES:
    81 				case DATABASES:
    71 				case FORMATTERS:
    82 				case FORMATTERS:
    72 				case TYPES:
    83 				case TYPES:
    73 					formattinNeeded = true;
    84 					formattinNeeded = true;
    74 					break;
    85 					break;
    77 
    88 
    78 		if (formattinNeeded) {
    89 		if (formattinNeeded) {
    79 			try (Formatter f = getFormatter()) {
    90 			try (Formatter f = getFormatter()) {
    80 				formatter = f;
    91 				formatter = f;
    81 				formatter.writeStartBatch();
    92 				formatter.writeStartBatch();
    82 				formatter.writeStartDatabase(new DatabaseDefinition());
    93 				DatabaseDefinition dd = new DatabaseDefinition();
    83 				formatter.writeStartStatement();
    94 				dd.setName(CONFIG_DB_NAME);
       
    95 				formatter.writeStartDatabase(dd);
    84 				showInfos(commands);
    96 				showInfos(commands);
    85 				formatter.writeEndStatement();
       
    86 				formatter.writeEndDatabase();
    97 				formatter.writeEndDatabase();
    87 				formatter.writeEndBatch();
    98 				formatter.writeEndBatch();
    88 				formatter.close();
    99 				formatter.close();
    89 			}
   100 			}
    90 		} else {
   101 		} else {
   115 
   126 
   116 		for (FormatterDefinition fd : configurationProvider.getConfiguration().getFormatters()) {
   127 		for (FormatterDefinition fd : configurationProvider.getConfiguration().getFormatters()) {
   117 			data.add(new Object[]{fd.getName(), false, defaultFormatter.equals(fd.getName()), fd.getClassName()});
   128 			data.add(new Object[]{fd.getName(), false, defaultFormatter.equals(fd.getName()), fd.getClassName()});
   118 		}
   129 		}
   119 
   130 
   120 		printTable(formatter, header, data);
   131 		printTable(formatter, header, data, "-- configured and built-in output formatters", null);
   121 
   132 
   122 
   133 
   123 	}
   134 	}
   124 
   135 
   125 	public void listTypes() throws FormatterException, ConfigurationException {
   136 	public void listTypes() throws FormatterException, ConfigurationException {
   126 		ColumnsHeader header = constructHeader(new HeaderField("name", SQLType.VARCHAR), new HeaderField("code", SQLType.INTEGER));
   137 		ColumnsHeader header = constructHeader(new HeaderField("name", SQLType.VARCHAR), new HeaderField("code", SQLType.INTEGER));
   127 		List<Object[]> data = new ArrayList<>();
   138 		List<Object[]> data = new ArrayList<>();
   128 		for (SQLType sqlType : SQLType.values()) {
   139 		for (SQLType sqlType : SQLType.values()) {
   129 			data.add(new Object[]{sqlType.name(), sqlType.getCode()});
   140 			data.add(new Object[]{sqlType.name(), sqlType.getCode()});
   130 		}
   141 		}
   131 		printTable(formatter, header, data);
   142 		printTable(formatter, header, data, "-- data types", null);
   132 		log.log(Level.INFO, "Type names in --types option are case insensitive");
   143 		log.log(Level.INFO, "Type names in --types option are case insensitive");
   133 	}
   144 	}
   134 
   145 
   135 	public void listDatabases() throws ConfigurationException, FormatterException {
   146 	public void listDatabases() throws ConfigurationException, FormatterException {
   136 		ColumnsHeader header = constructHeader(
   147 		ColumnsHeader header = constructHeader(
   146 			for (DatabaseDefinition dd : configuredDatabases) {
   157 			for (DatabaseDefinition dd : configuredDatabases) {
   147 				data.add(new Object[]{dd.getName(), dd.getUserName(), dd.getUrl()});
   158 				data.add(new Object[]{dd.getName(), dd.getUserName(), dd.getUrl()});
   148 			}
   159 			}
   149 		}
   160 		}
   150 
   161 
   151 		printTable(formatter, header, data);
   162 		printTable(formatter, header, data, "-- configured databases", null);
   152 	}
   163 	}
   153 
   164 
   154 	public void listJdbcDrivers() throws FormatterException, ConfigurationException {
   165 	public void listJdbcDrivers() throws FormatterException, ConfigurationException {
   155 		ColumnsHeader header = constructHeader(
   166 		ColumnsHeader header = constructHeader(
   156 				new HeaderField("class", SQLType.VARCHAR),
   167 				new HeaderField("class", SQLType.VARCHAR),
   165 			data.add(new Object[]{
   176 			data.add(new Object[]{
   166 				d.getClass().getName(),
   177 				d.getClass().getName(),
   167 				d.getMajorVersion() + "." + d.getMinorVersion(),
   178 				d.getMajorVersion() + "." + d.getMinorVersion(),
   168 				d.getMajorVersion(),
   179 				d.getMajorVersion(),
   169 				d.getMinorVersion(),
   180 				d.getMinorVersion(),
   170 				d.jdbcCompliant()});
   181 				d.jdbcCompliant()
   171 		}
   182 			});
   172 
   183 		}
   173 		printTable(formatter, header, data);
   184 
   174 
   185 		printTable(formatter, header, data, "-- discovered JDBC drivers (available on the CLASSPATH)", null);
       
   186 	}
       
   187 
       
   188 	public void listJdbcProperties() throws FormatterException, ConfigurationException {
       
   189 		for (String dbName : options.getDatabaseNamesToListProperties()) {
       
   190 			ColumnsHeader header = constructHeader(
       
   191 					new HeaderField("property_name", SQLType.VARCHAR),
       
   192 					new HeaderField("required", SQLType.BOOLEAN),
       
   193 					new HeaderField("choices", SQLType.ARRAY),
       
   194 					new HeaderField("configured_value", SQLType.VARCHAR),
       
   195 					new HeaderField("description", SQLType.VARCHAR));
       
   196 			List<Object[]> data = new ArrayList<>();
       
   197 
       
   198 			DatabaseDefinition dd = configurationProvider.getConfiguration().getDatabase(dbName);
       
   199 
       
   200 			Driver driver = findDriver(dd);
       
   201 
       
   202 			if (driver == null) {
       
   203 				log.log(Level.WARNING, "No JDBC driver was found for DB: {0} with URL: {1}", new Object[]{dd.getName(), dd.getUrl()});
       
   204 			} else {
       
   205 				log.log(Level.INFO, "For DB: {0} was found JDBC driver: {1}", new Object[]{dd.getName(), driver.getClass().getName()});
       
   206 
       
   207 				try {
       
   208 					DriverPropertyInfo[] propertyInfos = driver.getPropertyInfo(dd.getUrl(), dd.getProperties().getJavaProperties());
       
   209 
       
   210 					Set<String> standardProperties = new HashSet<>();
       
   211 
       
   212 					for (DriverPropertyInfo pi : propertyInfos) {
       
   213 						Array choices = new FakeSqlArray(pi.choices, SQLType.VARCHAR);
       
   214 						data.add(new Object[]{
       
   215 							pi.name,
       
   216 							pi.required,
       
   217 							choices.getArray() == null ? "" : choices,
       
   218 							pi.value == null ? "" : pi.value,
       
   219 							pi.description
       
   220 						});
       
   221 						standardProperties.add(pi.name);
       
   222 					}
       
   223 
       
   224 					for (Property p : dd.getProperties()) {
       
   225 						if (!standardProperties.contains(p.getName())) {
       
   226 							data.add(new Object[]{
       
   227 								p.getName(),
       
   228 								"",
       
   229 								"",
       
   230 								p.getValue(),
       
   231 								""
       
   232 							});
       
   233 							log.log(Level.WARNING, "Your configuration contains property „{0}“ not declared by the JDBC driver.", p.getName());
       
   234 						}
       
   235 					}
       
   236 
       
   237 				} catch (SQLException e) {
       
   238 					log.log(Level.WARNING, "Error during getting property infos.", e);
       
   239 				}
       
   240 
       
   241 				List<Parameter> parameters = new ArrayList<>();
       
   242 				parameters.add(new NamedParameter("databgase", dbName, SQLType.VARCHAR));
       
   243 				parameters.add(new NamedParameter("driver_class", driver.getClass().getName(), SQLType.VARCHAR));
       
   244 				parameters.add(new NamedParameter("driver_major_version", driver.getMajorVersion(), SQLType.INTEGER));
       
   245 				parameters.add(new NamedParameter("driver_minor_version", driver.getMinorVersion(), SQLType.INTEGER));
       
   246 
       
   247 				printTable(formatter, header, data, "-- configured and configurable JDBC driver properties", parameters);
       
   248 			}
       
   249 		}
       
   250 
       
   251 	}
       
   252 
       
   253 	private Driver findDriver(DatabaseDefinition dd) {
       
   254 		final ServiceLoader<Driver> drivers = ServiceLoader.load(Driver.class);
       
   255 		for (Driver d : drivers) {
       
   256 			try {
       
   257 				if (d.acceptsURL(dd.getUrl())) {
       
   258 					return d;
       
   259 				}
       
   260 			} catch (SQLException e) {
       
   261 				log.log(Level.WARNING, "Error during finding JDBC driver for: " + dd.getName(), e);
       
   262 			}
       
   263 		}
       
   264 		return null;
   175 	}
   265 	}
   176 
   266 
   177 	public void testConnection() throws FormatterException, ConfigurationException {
   267 	public void testConnection() throws FormatterException, ConfigurationException {
   178 		ColumnsHeader header = constructHeader(
   268 		ColumnsHeader header = constructHeader(
   179 				new HeaderField("database_name", SQLType.VARCHAR),
   269 				new HeaderField("database_name", SQLType.VARCHAR),
   183 
   273 
   184 		for (String dbName : options.getDatabaseNamesToTest()) {
   274 		for (String dbName : options.getDatabaseNamesToTest()) {
   185 			data.add(testConnection(dbName));
   275 			data.add(testConnection(dbName));
   186 		}
   276 		}
   187 
   277 
   188 		printTable(formatter, header, data);
   278 		printTable(formatter, header, data, "-- database configuration and connectivity test", null);
   189 	}
   279 	}
   190 
   280 
   191 	public Object[] testConnection(String dbName) {
   281 	public Object[] testConnection(String dbName) {
   192 		log.log(Level.FINE, "Testing connection to database: {0}", dbName);
   282 		log.log(Level.FINE, "Testing connection to database: {0}", dbName);
   193 
   283 
   226 
   316 
   227 	private void println(String line) {
   317 	private void println(String line) {
   228 		out.println(line);
   318 		out.println(line);
   229 	}
   319 	}
   230 
   320 
   231 	private void printTable(Formatter formatter, ColumnsHeader header, List<Object[]> data) throws ConfigurationException, FormatterException {
   321 	private void printTable(Formatter formatter, ColumnsHeader header, List<Object[]> data, String sql, List<Parameter> parameters) throws ConfigurationException, FormatterException {
       
   322 		formatter.writeStartStatement();
       
   323 
       
   324 		if (sql != null) {
       
   325 			formatter.writeQuery(sql);
       
   326 			if (parameters != null) {
       
   327 				formatter.writeParameters(parameters);
       
   328 			}
       
   329 		}
       
   330 
   232 		formatter.writeStartResultSet(header);
   331 		formatter.writeStartResultSet(header);
   233 
   332 
   234 		for (Object[] row : data) {
   333 		for (Object[] row : data) {
   235 			formatter.writeStartRow();
   334 			formatter.writeStartRow();
   236 			for (Object cell : row) {
   335 			for (Object cell : row) {
   238 			}
   337 			}
   239 			formatter.writeEndRow();
   338 			formatter.writeEndRow();
   240 		}
   339 		}
   241 
   340 
   242 		formatter.writeEndResultSet();
   341 		formatter.writeEndResultSet();
       
   342 		formatter.writeEndStatement();
   243 	}
   343 	}
   244 
   344 
   245 	private Formatter getFormatter() throws ConfigurationException, FormatterException {
   345 	private Formatter getFormatter() throws ConfigurationException, FormatterException {
   246 		String formatterName = options.getFormatterName();
   346 		String formatterName = options.getFormatterName();
   247 		formatterName = formatterName == null ? Configuration.DEFAULT_FORMATTER_PREFETCHING : formatterName;
   347 		formatterName = formatterName == null ? Configuration.DEFAULT_FORMATTER_PREFETCHING : formatterName;
   317 			@Override
   417 			@Override
   318 			public void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException {
   418 			public void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException {
   319 				infoLister.listJdbcDrivers();
   419 				infoLister.listJdbcDrivers();
   320 			}
   420 			}
   321 		},
   421 		},
       
   422 		JDBC_PROPERTIES {
       
   423 			@Override
       
   424 			public void showInfo(InfoLister infoLister) throws ConfigurationException, FormatterException {
       
   425 				infoLister.listJdbcProperties();
       
   426 			}
       
   427 		},
   322 		DATABASES {
   428 		DATABASES {
   323 			@Override
   429 			@Override
   324 			public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException {
   430 			public void showInfo(InfoLister infoLister) throws FormatterException, ConfigurationException {
   325 				infoLister.listDatabases();
   431 				infoLister.listDatabases();
   326 			}
   432 			}