/** * Copyright (C) 2000 - 2009 Silverpeas * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * As a special exception to the terms and conditions of version 3.0 of the GPL, you may * redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS") * applications as described in Silverpeas's FLOSS exception. You should have received a copy of the * text describing the FLOSS exception, and it is also available here: * "http://repository.silverpeas.com/legal/licensing" * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ package org.silverpeas.dbbuilder; import java.io.File; import java.io.DataInputStream; import java.io.FileInputStream; import java.lang.reflect.Method; import org.silverpeas.file.StringUtil; import org.silverpeas.dbbuilder.sql.ConnectionFactory; import org.silverpeas.dbbuilder.sql.QueryExecutor; import org.silverpeas.dbbuilder.sql.DbProcParameter; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Enumeration; import java.util.Properties; import org.silverpeas.dbbuilder.dbbuilder_dl.DbBuilderDynamicPart; import java.sql.ResultSet; import java.sql.Statement; public abstract class DBBuilderPiece { // identifiant unique pour toute la session private static Integer increment = new Integer(0); // identifiant de la pièce si elle est stockée en base private String actionInternalID = null; // nom de la pièce ou du fichier private String pieceName = null; // contenu initial de la pièce private String content = null; // nom de l'action private String actionName = null; // oui ou non fonctionnement en mode trace private boolean traceMode = false; // contenu interprété en séquence d'instructions protected Instruction[] instructions = null; protected Connection connection; protected Console console = null; // Contructeur utilisé pour une pièce de type fichier public DBBuilderPiece(String pieceName, String actionName, boolean traceMode) throws Exception { // mémorise le mode trace this.traceMode = traceMode; // mémorise l'action this.actionName = actionName; // mémorise le nom de la piece = le nom du fichier this.pieceName = pieceName; // Charge le contenu sauf pour un package if (pieceName.endsWith(".jar")) { content = ""; } else { // charge son contenu sauf pour un jar qui doit être dans le classpath File myFile = new File(pieceName); if (!myFile.exists() || !myFile.isFile() || !myFile.canRead()) { DBBuilder.printMessageln(Console.NEW_LINE + "\t\t***Unable to load : " + pieceName); throw new Exception("Unable to find or load : " + pieceName); } int fileSize = (int) myFile.length(); byte[] data = new byte[fileSize]; DataInputStream in = new DataInputStream(new FileInputStream(pieceName)); in.readFully(data); content = new String(data); in.close(); } Properties res = DBBuilder.getdbBuilderResources(); if (res != null) { for (Enumeration e = res.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); String value = res.getProperty(key); content = StringUtil.sReplace("${" + key + "}", value, content); } } } // Contructeur utilisé pour une pièce de type chaîne en mémoire public DBBuilderPiece(String pieceName, String actionName, String content, boolean traceMode) throws Exception { // mémorise le mode trace this.traceMode = traceMode; // mémorise l'action this.actionName = actionName; // mémorise le nom du fichier this.pieceName = pieceName; // mémorise le contenu this.content = content; } // Contructeur utilisé pour une pièce stockée en base de données public DBBuilderPiece(String actionInternalID, String pieceName, String actionName, int itemOrder, boolean traceMode) throws Exception { // mémorise le mode trace this.traceMode = traceMode; // mémorise l'action this.actionName = actionName; // mémorise le nom du fichier this.pieceName = pieceName; // mémorise l'ID interne de la base this.actionInternalID = actionInternalID; // charge et mémorise le contenu this.content = getContentFromDB(actionInternalID); } public String getActionInternalID() { return actionInternalID; } public String getPieceName() { return pieceName; } public String getActionName() { return actionName; } /* * retourne le contenu du fichier */ public String getContent() { // retourne le contenu chargé return content; } public void setConsole(final Console console) { this.console = console; } public Console getConsole() { return this.console; } /* * retourne si oui/non mode trace */ public boolean isTraceMode() { // retourne le mode de trace return traceMode; } public abstract void setInstructions(); public abstract void cacheIntoDB(Connection connection, String _package, int _itemOrder) throws Exception; public Instruction[] getInstructions() { return instructions; } public void traceInstructions() { for (Instruction instruction : instructions) { System.out.println(instruction.getInstructionText()); } } /** * Execute via JDBC la séquence d'instructions élémentaires conservées sur instructions[] */ public void executeInstructions(Connection connection) throws Exception { setConnection(connection); // try { for (Instruction instruction : instructions) { String currentInstruction = instruction.getInstructionText(); switch (instruction.getInstructionType()) { case Instruction.IN_INVOKEJAVA: executeJavaInvoke(currentInstruction, instruction.getInstructionDetail()); break; case Instruction.IN_CALLDBPROC: executeSingleProcedure(currentInstruction, (DbProcParameter[]) instruction. getInstructionDetail()); break; case Instruction.IN_UPDATE: default: executeSingleUpdate(currentInstruction); break; } } } // Cache en BD via JDBC une séquence de désinstallation // le paramètre est la liste des valeurs à insérer dans la table // SR_UNINSTITEMS public void cacheIntoDB(Connection connexion, String _package, int _itemOrder, String _pieceType, String _delimiter, Integer _keepDelimiter, String _dbProcName) throws Exception { setConnection(connexion); PreparedStatement pstmt = null; try { // insertion SR_UNINSTITEMS Long theLong = new Long(System.currentTimeMillis()); String itemID = theLong.toString() + "-" + getIncrement().toString(); pstmt = connexion.prepareStatement("insert into SR_UNINSTITEMS(SR_ITEM_ID, " + "SR_PACKAGE, SR_ACTION_TAG, SR_ITEM_ORDER, SR_FILE_NAME, SR_FILE_TYPE, SR_DELIMITER, " + "SR_KEEP_DELIMITER, SR_DBPROC_NAME) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?)"); pstmt.setString(1, itemID); pstmt.setString(2, _package); pstmt.setString(3, actionName); pstmt.setInt(4, _itemOrder); pstmt.setString(5, pieceName); pstmt.setString(6, _pieceType); pstmt.setString(7, _delimiter); pstmt.setInt(8, _keepDelimiter); pstmt.setString(9, _dbProcName); pstmt.executeUpdate(); // insertion SR_SCRIPTS final String[] subS = getSubStrings(content); pstmt = connexion.prepareStatement("insert into SR_SCRIPTS(SR_ITEM_ID, SR_SEQ_NUM, SR_TEXT) " + "values (?, ?, ? )"); for (int i = 0; i < subS.length; i++) { pstmt.setString(1, itemID); pstmt.setInt(2, i); pstmt.setString(3, subS[i]); pstmt.executeUpdate(); } } catch (Exception ex) { ex.printStackTrace(); throw new Exception("\n\t\t***ERROR RETURNED BY THE RDBMS : " + ex.getMessage() + "\n", ex); } finally { if (pstmt != null) { pstmt.close(); } } } public void executeSingleUpdate(String currentInstruction) throws Exception { if (traceMode) { String printableInstruction = StringUtil.sReplace("\r\n", " ", currentInstruction); printableInstruction = StringUtil.sReplace("\t", " ", printableInstruction); if (printableInstruction.length() > 147) { printableInstruction = printableInstruction.substring(0, 146) + "..."; } DBBuilder.printMessageln("\t\t>" + printableInstruction); } Statement stmt = connection.createStatement(); try { stmt.executeUpdate(currentInstruction); } catch (Exception e) { throw new Exception("\n\t\t***ERROR RETURNED BY THE RDBMS : " + e.getMessage() + "\n\t\t***STATEMENT ON ERROR IS : " + "\n" + currentInstruction + "\n\t\t" + pieceName, e); } finally { stmt.close(); } } public void executeSingleProcedure(String currentInstruction, DbProcParameter[] params) throws Exception { if (traceMode) { String printableInstruction = StringUtil.sReplace("\n", " ", currentInstruction); printableInstruction = StringUtil.sReplace("\t", " ", printableInstruction); if (printableInstruction.length() > 147) { printableInstruction = printableInstruction.substring(0, 146) + "..."; } DBBuilder.printMessageln("\t\t>" + printableInstruction); } try { QueryExecutor.executeProcedure(connection, currentInstruction, params); } catch (Exception e) { throw new Exception("\n\t\t***ERROR RETURNED BY THE RDBMS : " + e.getMessage() + "\n\t\t***STATEMENT ON ERROR IS : " + "\n" + currentInstruction, e); } } public void executeJavaInvoke(String currentInstruction, Object myClass) throws Exception { if (traceMode) { DBBuilder.printMessageln("\t\t>" + myClass.getClass().getName() + "." + currentInstruction + "()"); } ((DbBuilderDynamicPart) myClass).setConnection(connection); Method methode = myClass.getClass().getMethod(currentInstruction); if (methode == null) { throw new Exception("No method \"" + currentInstruction + "\" defined for \"" + myClass.getClass().getName() + "\" class."); } try { methode.invoke(myClass); } catch (Exception e) { throw new Exception("\n\t\t***ERROR RETURNED BY THE JVM : " + e.getMessage(), e); } } private String getSqlStringValue(String s) { if (s == null) { return s; } return "'" + StringUtil.sReplace("'", "''", s) + "'"; } private String[] getSubStrings(String str) { int maxl = 1100; int nbS = str.length() / maxl; if ((str.length() - nbS * maxl) > 0) { nbS++; } String tmpS = new String(str); String[] retS = new String[nbS]; for (int i = 0; i < nbS; i++) { if (i == nbS - 1) { retS[i] = tmpS; } else { retS[i] = tmpS.substring(0, maxl - 1); tmpS = tmpS.substring(maxl - 1); } } return retS; } private synchronized Integer getIncrement() { return increment++; } private String getContentFromDB(String itemID) throws Exception { Connection connexion = null; StringBuilder dbContent = new StringBuilder(""); try { connexion = ConnectionFactory.getConnection(); PreparedStatement pstmt = connexion.prepareStatement("select SR_SEQ_NUM, SR_TEXT from " + "SR_SCRIPTS where SR_ITEM_ID = ? order by 1"); pstmt.setString(1, itemID); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { dbContent = dbContent.append(rs.getString("SR_TEXT")); } rs.close(); pstmt.close(); } catch (Exception e) { throw new Exception("\n\t\t***ERROR RETURNED BY THE JVM : " + e.getMessage() + "\n\t\t\t(" + "select SR_SEQ_NUM, SR_TEXT from " + "SR_SCRIPTS where SR_ITEM_ID = '" + itemID + "' order by 1" + ")"); } return dbContent.toString(); } public void setConnection(Connection connection) { this.connection = connection; } }