Java tutorial
/* * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wso2.carbon.is.migration.service; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.core.migrate.MigrationClientException; import org.wso2.carbon.is.migration.internal.ISMigrationServiceDataHolder; import org.wso2.carbon.is.migration.util.Constant; import org.wso2.carbon.is.migration.util.Utility; import org.wso2.carbon.utils.dbcreator.DatabaseCreator; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.StringTokenizer; import static org.wso2.carbon.is.migration.util.Constant.IDENTITY_DB_SCRIPT; import static org.wso2.carbon.is.migration.util.Constant.UM_DB_SCRIPT; /** * Migrator implementation for Schema migration. */ public class SchemaMigrator extends Migrator { private static final Log log = LogFactory.getLog(SchemaMigrator.class); public static final String LOCATION = "location"; private String location; private Connection conn = null; private Statement statement; private String delimiter = ";"; @Override public void migrate() throws MigrationClientException { this.location = getMigratorConfig().getParameterValue(LOCATION); log.info(Constant.MIGRATION_LOG + "Executing Identity Migration Scripts."); try { conn = getDataSource().getConnection(); conn.setAutoCommit(false); String databaseType = DatabaseCreator.getDatabaseType(this.conn); if ("mysql".equals(databaseType)) { Utility.setMySQLDBName(conn); if (this.conn.getMetaData().getDatabaseProductVersion().startsWith("5.7")) { databaseType = "mysql5.7"; } } statement = conn.createStatement(); String dbscriptName = Utility.getSchemaPath(getSchema(), databaseType, location, getVersionConfig().getVersion()); executeSQLScript(dbscriptName); conn.commit(); log.info(Constant.MIGRATION_LOG + "Identity DB Migration script executed successfully."); } catch (Exception e) { log.error(e); if (!isContinueOnError()) { throw new MigrationClientException(e.getMessage(), e); } } finally { try { if (statement != null) { statement.close(); } } catch (SQLException e) { log.error("Failed to close database statement.", e); } try { if (conn != null) { conn.close(); } } catch (SQLException e) { log.error("Failed to close database connection.", e); } } } /** * executes content in SQL script * * @return StringBuffer * @throws Exception */ private void executeSQLScript(String dbscriptName) throws Exception { String databaseType = DatabaseCreator.getDatabaseType(this.conn); boolean keepFormat = false; if ("oracle".equals(databaseType)) { delimiter = "/"; } else if ("db2".equals(databaseType)) { delimiter = "/"; } else if ("openedge".equals(databaseType)) { delimiter = "/"; keepFormat = true; } StringBuffer sql = new StringBuffer(); BufferedReader reader = null; try { InputStream is = new FileInputStream(dbscriptName); reader = new BufferedReader(new InputStreamReader(is)); String line; while ((line = reader.readLine()) != null) { line = line.trim(); if (!keepFormat) { if (line.startsWith("//")) { continue; } if (line.startsWith("--")) { continue; } StringTokenizer st = new StringTokenizer(line); if (st.hasMoreTokens()) { String token = st.nextToken(); if ("REM".equalsIgnoreCase(token)) { continue; } } } //add the oracle database owner if ("oracle".equals(databaseType) && line.contains("databasename :=")) { if (dbscriptName.contains(IDENTITY_DB_SCRIPT)) { line = "databasename := '" + ISMigrationServiceDataHolder.getIdentityOracleUser() + "';"; } else if (dbscriptName.contains(UM_DB_SCRIPT)) { line = "databasename := '" + ISMigrationServiceDataHolder.getUmOracleUser() + "';"; } } sql.append(keepFormat ? "\n" : " ").append(line); // SQL defines "--" as a comment to EOL // and in Oracle it may contain a hint // so we cannot just remove it, instead we must end it if (!keepFormat && line.indexOf("--") >= 0) { sql.append("\n"); } if ((DatabaseCreator.checkStringBufferEndsWith(sql, delimiter))) { executeSQL(sql.substring(0, sql.length() - delimiter.length())); sql.replace(0, sql.length(), ""); } } // Catch any statements not followed by ; if (sql.length() > 0) { executeSQL(sql.toString()); } } catch (Exception e) { log.error("Error occurred while executing SQL script for migrating database", e); throw new Exception("Error occurred while executing SQL script for migrating database", e); } finally { if (reader != null) { reader.close(); } } } /** * executes given sql * * @param sql * @throws Exception */ private void executeSQL(String sql) throws Exception { // Check and ignore empty statements if ("".equals(sql.trim())) { return; } ResultSet resultSet = null; try { if (log.isDebugEnabled()) { log.debug("SQL : " + sql); } boolean ret; int updateCount = 0, updateCountTotal = 0; ret = statement.execute(sql); updateCount = statement.getUpdateCount(); resultSet = statement.getResultSet(); do { if (!ret && updateCount != -1) { updateCountTotal += updateCount; } ret = statement.getMoreResults(); if (ret) { updateCount = statement.getUpdateCount(); resultSet = statement.getResultSet(); } } while (ret); if (log.isDebugEnabled()) { log.debug(sql + " : " + updateCountTotal + " rows affected"); } SQLWarning warning = conn.getWarnings(); while (warning != null) { log.debug(warning + " sql warning"); warning = warning.getNextWarning(); } conn.clearWarnings(); } catch (SQLException e) { if (e.getSQLState().equals("X0Y32") || e.getSQLState().equals("42710")) { // eliminating the table already exception for the derby and DB2 database types if (log.isDebugEnabled()) { log.info("Table Already Exists. Hence, skipping table creation"); } } else { throw new Exception("Error occurred while executing : " + sql, e); } } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.error("Error occurred while closing result set.", e); } } } } }