package com.rjconsultores.ventaboletos; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import org.apache.log4j.Logger; import org.flywaydb.core.Flyway; import org.flywaydb.core.api.callback.FlywayCallback; import com.rjconsultores.ventaboletos.vo.FlyWayCustomDetail; public class FlyWay { private static Logger log = Logger.getLogger(FlyWay.class); private static final FlyWay INSTANCE = new FlyWay(); final private static String TABELA_FLYWAY = "schema_version_cst"; final File JBOSS_DATA = new File(System.getProperty("jboss.server.data.dir")); private DataSource dataSource = null; private String url = null; private String user = null; private String password = null; private String location = "db.migration"; public static FlyWay getInstance() { return INSTANCE; } public void defineLocation(final String location) { this.location = location; } public void defineDataSource(final DataSource dataSource) { this.dataSource = dataSource; fixFiles(dataSource); } public void defineProperties(final String url, final String user, final String password) { this.url = url; this.user = user; this.password = password; } private void fixFiles(final DataSource ds) { try { Connection c = dataSource.getConnection(); Statement s = c.createStatement(); fixVersion(s, "20161710.1833", "20161017.1833", "V20161017_1833__mantis8112.sql"); fixVersion(s, "20161910.0934", "20161019.0934", "V20161019_0934__mantis7907.sql"); fixVersion(s, "20162410.1119", "20161024.1119", "V20161024_1119__mantis7904.sql"); s.close(); } catch (SQLException e) { log.error(e.getMessage(), e); } } private void fixVersion(final Statement s, final String oldVersion, final String newVersion, final String newScript) throws SQLException { ResultSet rs = s.executeQuery("select count(*) as total from \"schema_version\" where \"version\" like '" + oldVersion + "'"); int total = 0; while (rs.next()) { total = rs.getInt("total"); } rs.close(); if (total > 0) { log.info("Fix version " + oldVersion + " to new version " + newVersion + " and new script " + newScript); StringBuilder sql = new StringBuilder(""); sql.append(" update \"schema_version\""); sql.append(" set \"version\" = '" + newVersion + "', \"script\" = '" + newScript + "'"); sql.append(" where \"version\" like '" + oldVersion + "'"); s.executeUpdate(sql.toString()); } } public boolean start() { return start(null, null); } public boolean startCustom() { String location = "db.performance"; if (JBOSS_DATA != null) { File data = new File(JBOSS_DATA, "flyway"); if (!data.exists()) { data.mkdirs(); } if (!validarScripts(data)) { return true; } location = "filesystem:" + data.getPath(); } return start(location, TABELA_FLYWAY); } public boolean start(final String customLocation, final String customTable) { log.info("Executando Flyway..."); try{ final Flyway flyway = new Flyway(); if (customTable != null) { flyway.setTable(customTable); } if (customLocation != null) { flyway.setLocations(customLocation); } else if (this.location != null && !this.location.equals("db.migration")) { flyway.setLocations(this.location); } if (dataSource != null) { flyway.setDataSource(dataSource); } else { flyway.setDataSource(url, user, password); dataSource = flyway.getDataSource(); } execute(flyway); }catch(Throwable t){ log.error("Erro ao executar o Flyway",t); return false; } log.info("Flyway executado."); return true; } public void execute(final Flyway flyway) { flyway.setValidateOnMigrate(false); flyway.setIgnoreFutureMigrations(true); flyway.setOutOfOrder(true); flyway.setBaselineOnMigrate(true); if (flyway.getTable().equals(TABELA_FLYWAY)) { FlyWayCallback errorCallback = new FlyWayCallback(); FlywayCallback[] callbacks = new FlywayCallback[]{ errorCallback }; flyway.setCallbacks(callbacks); try { flyway.migrate(); } catch (final Exception e) { if (errorCallback.getScriptError() != null) { log.error("[Flyway] Erro ao executar o script: " + errorCallback.getScriptError() + ". Este script sera desabilitado na tabela FLYWAY_SCRIPTS."); File scriptFile = new File(JBOSS_DATA, "flyway"); scriptFile = new File(scriptFile, errorCallback.getScriptError()); if (scriptFile.exists()) { log.info("[Flyway] Excluindo fisicamente o script: " + errorCallback.getScriptError() + ". " + (scriptFile.delete() ? "OK" : "ERROR")); } try { Connection c = flyway.getDataSource().getConnection(); PreparedStatement ps = c.prepareStatement("update flyway_scripts set activo = 0 where nome like ?"); ps.setString(1, errorCallback.getScriptError().replace(".sql", "")); ps.executeUpdate(); } catch (SQLException e1) { } } flyway.repair(); } } else { flyway.migrate(); } } private boolean validarScripts(File data) { Map scripts = new HashMap(0); try { StringBuilder sb = new StringBuilder(); sb.append(" select nome as nome_arquivo, sql as sql_arquivo, sql_erro as erro, datahora_execucao as datahora"); sb.append(" from flyway_scripts"); sb.append(" where activo = 1 and nome not in (select replace(\"script\", '.sql', '') from \"schema_version_cst\")"); sb.append(" order by nome_arquivo"); Connection c = dataSource.getConnection(); Statement s = c.createStatement(); ResultSet rs = s.executeQuery(sb.toString()); while (rs.next()) { Timestamp timestamp = rs.getTimestamp("datahora"); FlyWayCustomDetail detail = new FlyWayCustomDetail(); detail.setVersion(rs.getString("nome_arquivo")); detail.setSql(rs.getString("sql_arquivo")); detail.setErrorCode(rs.getString("erro")); if (timestamp != null) { detail.setDatetimeExecute(new java.util.Date(timestamp.getTime())); } scripts.put(rs.getString("nome_arquivo"), detail); } rs.close(); s.close(); } catch (SQLException e) { log.error(e.getMessage(), e); } if (scripts.isEmpty()) { return false; } boolean retorno = false; Writer writer = null; for (Map.Entry entry : scripts.entrySet()) { if (entry.getValue().getDatetimeExecute() != null) { Calendar atual = Calendar.getInstance(); if (atual.getTime().before(entry.getValue().getDatetimeExecute())) { continue; } } File scriptFile = new File(data, entry.getKey() + ".sql"); if (scriptFile.exists()) { scriptFile.delete(); } if (!scriptFile.exists()) { StringBuilder sb = new StringBuilder(); if (entry.getValue().getErrorCode() != null) { sb.append("declare").append("\n"); sb.append(" object_exists exception;").append("\n").append("\n"); sb.append(" pragma exception_init (object_exists , ").append(entry.getValue().getErrorCode()).append(");").append("\n"); sb.append("begin").append("\n"); sb.append(" execute immediate '").append(entry.getValue().getSql()).append("';").append("\n"); sb.append(" exception when object_exists then null;").append("\n"); sb.append("end;"); } else { sb.append(entry.getValue().getSql()); } try { writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(scriptFile), "utf-8")); writer.write(sb.toString()); log.info("[Flyway] Script gerado: " + scriptFile.toString()); retorno = true; } catch (IOException ex) { } finally { try {writer.close();} catch (Exception ex) {log.info(ex.getMessage(), ex);} } } } return retorno; } }