/* * Copyright (c) 2005-2011 Grameen Foundation USA * 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. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.framework.persistence; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; /** * Utility methods for running SQL from files */ @SuppressWarnings( { "PMD.CyclomaticComplexity", "PMD.AssignmentInOperand", "PMD.AppendCharacterWithChar", "PMD.AvoidThrowingRawExceptionTypes", "PMD.DoNotThrowExceptionInFinally" }) public class SqlExecutor { @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = { "OBL_UNSATISFIED_OBLIGATION", "SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE" }, justification = "The resource is closed and the string cannot be static.") @SuppressWarnings("PMD.CloseResource") // Rationale: It's closed. public static void execute(InputStream stream, Connection conn) throws SQLException { String[] sqls = readFile(stream); boolean wasAutoCommit = conn.getAutoCommit(); // Entring: Set auto commit false if auto commit was true if (wasAutoCommit) { conn.setAutoCommit(false); } Statement statement = conn.createStatement(); for (String sql : sqls) { statement.addBatch(sql); } statement.executeBatch(); statement.close(); // Leaving: Commit only if auto commit was true, Set auto commit true only if auto commit was true if (wasAutoCommit) { conn.commit(); conn.setAutoCommit(true); } } public static void executeMultipleFiles(InputStream[] streams, Connection conn) throws SQLException { for(InputStream stream : streams) { execute(stream, conn); } } /** * Closes the stream when done. * * @return individual statements * */ @SuppressWarnings( { "PMD.CyclomaticComplexity", "PMD.AssignmentInOperand", "PMD.AppendCharacterWithChar", "PMD.AvoidThrowingRawExceptionTypes", "PMD.DoNotThrowExceptionInFinally" }) // Rationale: If the Apache Ant team thinks it's OK, we do too. Perhaps bad // reasoning, but inshallah. public static String[] readFile(InputStream stream) { // mostly ripped from // http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SQLExec.java try { ArrayList<String> statements = new ArrayList<String>(); Charset utf8 = Charset.forName("UTF-8"); CharsetDecoder decoder = utf8.newDecoder(); BufferedReader in = new BufferedReader(new InputStreamReader(stream, decoder)); StringBuffer sql = new StringBuffer(); String line; boolean insideProcedure = false; while ((line = in.readLine()) != null) { if (line.startsWith("//") || line.startsWith("--") || line.startsWith("DELIMITER")) { continue; } else if (line.startsWith("BEGIN") || line.startsWith("END */")) { insideProcedure = insideProcedure ^ true; } line = line.trim(); if ("".equals(line)) { continue; } sql.append("\n"); sql.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 (line.indexOf("--") >= 0) { sql.append("\n"); } if (sql.length() > 0 && sql.charAt(sql.length() - 1) == ';' && !insideProcedure) { statements.add(sql.substring(0, sql.length() - 1)); sql.setLength(0); } } // Catch any statements not followed by ; if (sql.length() > 0) { statements.add(sql.toString()); } return statements.toArray(new String[statements.size()]); } catch (IOException e) { throw new RuntimeException(e); } finally { try { stream.close(); } catch (IOException e) { throw new RuntimeException(e); } } } }