class DatabaseMetadataUtil {

    public static DatabaseMetadata getMetadata( Connection conn,
                                                boolean includeCatalogs,
                                                boolean includeSchemas ) throws Exception {
        try {
            DatabaseMetadata result = new DatabaseMetadata( );
            ResultSet rs;
            DatabaseMetaData sqlMetadata = conn.getMetaData( );

            result.setDatabaseType( DatabaseMetadataUtil.getDatabaseType( sqlMetadata.getDatabaseProductName() ) );
            result.setDatabaseProductName( sqlMetadata.getDatabaseProductName( ) );
            result.setDatabaseProductVersion( sqlMetadata.getDatabaseProductVersion( ) );
            result.setDriverName( sqlMetadata.getDriverName( ) );
            result.setDriverVersion( sqlMetadata.getDriverVersion( ) );
            result.setDriverMajorVersion( sqlMetadata.getDriverMajorVersion() );
            result.setDriverMinorVersion( sqlMetadata.getDriverMinorVersion( ) );

            if ( includeCatalogs ) {
                List< CatalogMetadata > catalogs = new ArrayList<>( );
                rs = sqlMetadata.getCatalogs( );
                while ( rs.next( ) ) {
                    catalogs.add( new CatalogMetadata( rs.getString( "TABLE_CAT" ) ) );
                }
                rs.close( );
                result.setCatalogs( catalogs );
            }

            if ( includeSchemas ) {
                List< SchemaMetadata > schemas = new ArrayList<>( );
                rs = sqlMetadata.getSchemas( );
                while ( rs.next( ) ) {
                    schemas.add( new SchemaMetadata( rs.getString( "TABLE_CATALOG" ), rs.getString( "TABLE_SCHEM" ) ) );
                }
                rs.close( );
                result.setSchemas( schemas );
            }
            return result;
        } catch ( Exception e ) {
            throw new Exception( "It was not possible to read database metadata due to the following error: "
                    + e.getMessage( ) );
        } finally {
            try {
                conn.close( );
            } catch ( Exception e ) {
                //we are not interested in raising this error case.
            }
        }
    }

}