SQLScriptBuilder.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.core.commons;

  21. import java.io.BufferedReader;
  22. import java.io.ByteArrayOutputStream;
  23. import java.io.File;
  24. import java.io.FileInputStream;
  25. import java.io.FileReader;
  26. import java.util.Arrays;
  27. import java.util.Properties;

  28. import org.openspcoop2.utils.TipiDatabase;
  29. import org.openspcoop2.utils.resources.FileSystemUtilities;

  30. /**
  31.  * SQLScriptBuilder
  32.  *
  33.  * @author Poli Andrea (apoli@link.it)
  34.  * @author $Author$
  35.  * @version $Rev$, $Date$
  36.  */
  37. public class SQLScriptBuilder {

  38.     public static void main(String[] args) throws Exception {
  39.         // Metodo utilizzato dal setup antinstaller
  40.        
  41.         String sqlSourceDir = (String) args[0];
  42.        
  43.         String sqlDestDir = (String) args[1];
  44.        
  45.         String sqlScriptName = (String) args[2];
  46.        
  47.         String modalitaInstallazione = (String) args[3];
  48.        
  49.         boolean splitDDL_DML = true;
  50.        
  51.         String versionePrecedente = null;
  52.         String versioneAttuale = null;
  53.         String tipoDatabase = null;
  54.         String configurazioneUpgrade = null;
  55.         boolean configurazioneUpgrade_runtime = true;
  56.         boolean configurazioneUpgrade_config = true;
  57.         boolean configurazioneUpgrade_tracce = true;
  58.         boolean configurazioneUpgrade_statistiche = true;
  59.         boolean configurazioneUpgrade_monitoraggio = true;
  60.         if(args.length>4){
  61.             versionePrecedente = (String) args[4];
  62.             versioneAttuale = (String) args[5];
  63.             tipoDatabase = (String) args[6];
  64.             if("aggiornamento".equals(modalitaInstallazione) && args.length>7){
  65.                 configurazioneUpgrade = (String) args[7];
  66.                 File f = new File(configurazioneUpgrade);
  67.                 if(f.exists()) {
  68.                     try(FileInputStream fin = new FileInputStream(f)){
  69.                         Properties p = new Properties();
  70.                         p.load(fin);
  71.                         configurazioneUpgrade_runtime = readBooleanProperty(p, "upgrade.runtime");
  72.                         configurazioneUpgrade_config = readBooleanProperty(p, "upgrade.configurazione");
  73.                         configurazioneUpgrade_tracce = readBooleanProperty(p, "upgrade.tracciamento");
  74.                         configurazioneUpgrade_statistiche = readBooleanProperty(p, "upgrade.statistiche");
  75.                         configurazioneUpgrade_monitoraggio = readBooleanProperty(p, "upgrade.monitoraggio");
  76.                     }
  77.                 }
  78.             }
  79.         }
  80.        
  81.         // NOTA: Non far stampare niente, viene usato come meccanismo di check per vedere se l'esecuzione e' andata a buon fine
  82.         //System.out.println("Modalita ["+modalitaInstallazione+"]");
  83.        
  84.         if("nuova".equals(modalitaInstallazione)){
  85.             buildSql_NuovaInstallazione(new File(sqlSourceDir),new File(sqlDestDir),sqlScriptName,splitDDL_DML);
  86.         }
  87.         else if("aggiornamento".equals(modalitaInstallazione)){
  88.            
  89.             //System.out.println("versionePrecedente ["+versionePrecedente+"]");
  90.             //System.out.println("versioneAttuale ["+versioneAttuale+"]");
  91.             //System.out.println("tipoDatabase ["+tipoDatabase+"]");
  92.            
  93.             buildSql_Aggiornamento(new File(sqlSourceDir),new File(sqlDestDir),sqlScriptName,versionePrecedente,
  94.                     versioneAttuale, tipoDatabase,
  95.                     configurazioneUpgrade_runtime,
  96.                     configurazioneUpgrade_config,
  97.                     configurazioneUpgrade_tracce,
  98.                     configurazioneUpgrade_statistiche,
  99.                     configurazioneUpgrade_monitoraggio);
  100.         }
  101.         else{
  102.             throw new Exception("Modalità installazione ["+modalitaInstallazione+"] sconosciuta");
  103.         }
  104.        
  105.     }
  106.    
  107.     private static boolean readBooleanProperty(Properties p, String name) throws Exception {
  108.         String tmp = p.getProperty(name);
  109.         if(tmp==null) {
  110.             throw new Exception("Configurazione Upgrade non corretta, proprietà ["+name+"] non presente");
  111.         }
  112.         tmp = tmp.trim();
  113.         try {
  114.             return Boolean.valueOf(tmp);
  115.         }catch(Exception e) {
  116.             throw new Exception("Configurazione Upgrade non corretta, proprietà ["+name+"] non corretta: "+e.getMessage(),e);
  117.         }
  118.     }
  119.    
  120.     private static void buildSql_NuovaInstallazione(File sqlSourceDir, File sqlDestDir, String sqlScriptName,
  121.             boolean splitDDL_DML) throws Exception {
  122.        
  123.         if(sqlSourceDir.exists()==false){
  124.             throw new Exception("Source dir ["+sqlSourceDir.getAbsolutePath()+"] not exists");
  125.         }
  126.         if(sqlSourceDir.canRead()==false){
  127.             throw new Exception("Source dir ["+sqlSourceDir.getAbsolutePath()+"] cannot read");
  128.         }
  129.        
  130.         if(sqlDestDir.exists()==false){
  131.             throw new Exception("Dest dir ["+sqlDestDir.getAbsolutePath()+"] not exists");
  132.         }
  133.         if(sqlDestDir.canWrite()==false){
  134.             throw new Exception("Dest dir ["+sqlDestDir.getAbsolutePath()+"] cannot write");
  135.         }
  136.        
  137.         int prefix = 0;
  138.         ByteArrayOutputStream bout = new ByteArrayOutputStream();
  139.        
  140.         // BASE
  141.         File [] f = sqlSourceDir.listFiles();
  142.         if(f!=null) {
  143.             for (int i = 0; i < f.length; i++) {
  144.                 if(f[i].isFile()) {
  145.                     _createSql(sqlSourceDir, f[i].getName(),
  146.                             sqlDestDir, sqlScriptName, prefix, bout,
  147.                             splitDDL_DML);
  148.                 }
  149.             }
  150.         }
  151.        
  152.         File dest = new File(sqlDestDir, sqlScriptName);
  153.        
  154.         bout.flush();
  155.         bout.close();
  156.         FileSystemUtilities.writeFile(dest, bout.toByteArray());
  157.        
  158.         if(splitDDL_DML){
  159.            
  160.             //System.out.println("Split init ...");
  161.            
  162.             File destInit = new File(sqlDestDir, dest.getName().replace(".sql", "_init.sql"));
  163.             splitFileForDDLtoDML(dest, dest, destInit);
  164.         }
  165.    
  166.     }
  167.    
  168.     private static void buildSql_Aggiornamento(File sqlSourceDir, File sqlDestDir, String sqlScriptName,
  169.             String precedenteVersione, String versioneAttuale, String tipoDatabase,
  170.             boolean configurazioneUpgrade_runtime,
  171.             boolean configurazioneUpgrade_config,
  172.             boolean configurazioneUpgrade_tracce,
  173.             boolean configurazioneUpgrade_statistiche,
  174.             boolean configurazioneUpgrade_monitoraggio) throws Exception {

  175.        
  176.         if(sqlSourceDir.exists()==false){
  177.             throw new Exception("Source dir ["+sqlSourceDir.getAbsolutePath()+"] not exists");
  178.         }
  179.         if(sqlSourceDir.canRead()==false){
  180.             throw new Exception("Source dir ["+sqlSourceDir.getAbsolutePath()+"] cannot read");
  181.         }

  182.         if(sqlDestDir.exists()==false){
  183.             throw new Exception("Dest dir ["+sqlDestDir.getAbsolutePath()+"] not exists");
  184.         }
  185.         if(sqlDestDir.canWrite()==false){
  186.             throw new Exception("Dest dir ["+sqlDestDir.getAbsolutePath()+"] cannot write");
  187.         }
  188.        
  189.        
  190.        
  191.         if(precedenteVersione==null){
  192.             throw new Exception("Precedente versione non fornita");
  193.         }
  194.         if(precedenteVersione.contains(".")==false){
  195.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] ('.' not found)");
  196.         }
  197.         int indexOfFirstPoint = precedenteVersione.indexOf(".");
  198.         if(indexOfFirstPoint<=0){
  199.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] ('.' not found with index)");
  200.         }
  201.         String productVersionString = precedenteVersione.substring(0, indexOfFirstPoint);
  202.         int productVersion = -1;
  203.         try{
  204.             productVersion = Integer.parseInt(productVersionString);
  205.         }catch(Exception e){
  206.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (productVersion:"+productVersionString+"): "+e.getMessage(),e);
  207.         }
  208.         int indexOfSecondPoint = precedenteVersione.indexOf(".",indexOfFirstPoint+1);
  209.         if(indexOfSecondPoint<=0 || indexOfSecondPoint<=indexOfFirstPoint){
  210.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (second '.' not found)");
  211.         }
  212.         String majorVersionString = precedenteVersione.substring(indexOfFirstPoint+1, indexOfSecondPoint);
  213.         int majorVersion = -1;
  214.         try{
  215.             majorVersion = Integer.parseInt(majorVersionString);
  216.         }catch(Exception e){
  217.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (majorVersion:"+majorVersionString+"): "+e.getMessage(),e);
  218.         }
  219.         if(precedenteVersione.length()<=indexOfSecondPoint){
  220.             throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (length)");
  221.         }
  222.         String minorVersionString = precedenteVersione.substring(indexOfSecondPoint+1,precedenteVersione.length());
  223.         int minorVersion = -1;
  224.         try{
  225.             minorVersion = Integer.parseInt(minorVersionString);
  226.         }catch(Exception e){
  227.             //throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (minorVersion:"+minorVersionString+"): "+e.getMessage(),e);
  228.             // Potrebbe essere una BUILD VERSION
  229.             if(minorVersionString.contains("_")){
  230.                 String newMinor = minorVersionString.split("_")[0];
  231.                 try{
  232.                     minorVersion = Integer.parseInt(newMinor);
  233.                 }catch(Exception eInternal){
  234.                     throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (minorVersion:"+minorVersionString+" minorVersionBuildNumber:"+newMinor+"): "+eInternal.getMessage(),eInternal);
  235.                 }
  236.             }
  237.             else{
  238.                 throw new Exception("Precedente versione in un formato non corretto ["+precedenteVersione+"] (minorVersion:"+minorVersionString+"): "+e.getMessage(),e);
  239.             }
  240.            
  241.         }
  242.         //System.out.println(productVersion+"."+majorVersion+"."+minorVersion);
  243.        
  244.        
  245.         int tmpMajorVersion = majorVersion;
  246.         int tmpMinorVersion = minorVersion;
  247.        
  248.         if(tipoDatabase==null){
  249.             throw new Exception("TipoDatabase non fornito");
  250.         }
  251.         TipiDatabase tipiDatabase = TipiDatabase.toEnumConstant(tipoDatabase);
  252.         if(TipiDatabase.DEFAULT.equals(tipiDatabase)) {
  253.             throw new Exception("TipoDatabase fornito ["+tipoDatabase+"] non valido");
  254.         }
  255.        
  256.         ByteArrayOutputStream bout = new ByteArrayOutputStream();
  257.         File infoVersion = null;
  258.        
  259.         while(true){
  260.            
  261.             String actualVersion = productVersion+"."+tmpMajorVersion+"."+tmpMinorVersion;
  262.             String nextVersion = productVersion+"."+tmpMajorVersion+"."+(tmpMinorVersion+1);
  263.             File version = new File(sqlSourceDir,"upgrade_"+actualVersion+"_to_"+nextVersion);
  264.             //System.out.println("CHECK ["+version.getAbsolutePath()+"] ["+version.exists()+"]");
  265.             if(version.exists()){
  266.                 if(version.canRead()==false){
  267.                     throw new Exception("Source version dir ["+version.getAbsolutePath()+"] cannot read");
  268.                 }
  269.                
  270.                 File tmp = _createSql_Aggiornamento(version, sqlDestDir, bout, nextVersion, tipoDatabase,
  271.                         configurazioneUpgrade_runtime,
  272.                         configurazioneUpgrade_config,
  273.                         configurazioneUpgrade_tracce,
  274.                         configurazioneUpgrade_statistiche,
  275.                         configurazioneUpgrade_monitoraggio);
  276.                 if(tmp!=null) {
  277.                     infoVersion = tmp;
  278.                 }
  279.                
  280.                 tmpMinorVersion++;
  281.             }
  282.             else{
  283.                 // check upgrade to major version +1
  284.                 actualVersion = productVersion+"."+tmpMajorVersion+".x";
  285.                 nextVersion = productVersion+"."+(tmpMajorVersion+1)+".0";
  286.                 version = new File(sqlSourceDir,"upgrade_"+actualVersion+"_to_"+nextVersion);
  287.                 //System.out.println("CHECK UPGRADE ["+version.getAbsolutePath()+"] ["+version.exists()+"]");
  288.                 if(version.exists()){
  289.                     if(version.canRead()==false){
  290.                         throw new Exception("Source version dir ["+version.getAbsolutePath()+"] cannot read");
  291.                     }
  292.                    
  293.                     File tmp = _createSql_Aggiornamento(version, sqlDestDir, bout, nextVersion, tipoDatabase,
  294.                             configurazioneUpgrade_runtime,
  295.                             configurazioneUpgrade_config,
  296.                             configurazioneUpgrade_tracce,
  297.                             configurazioneUpgrade_statistiche,
  298.                             configurazioneUpgrade_monitoraggio);
  299.                     if(tmp!=null) {
  300.                         infoVersion = tmp;
  301.                     }
  302.                    
  303.                     tmpMajorVersion++;
  304.                     tmpMinorVersion=0;
  305.                 }
  306.                 else{
  307.                     break;
  308.                 }
  309.             }
  310.            
  311.         }
  312.        
  313.         if(infoVersion!=null) {
  314.             byte[] content = FileSystemUtilities.readBytesFromFile(infoVersion);
  315.             bout.write("\n\n".getBytes());
  316.             bout.write(content);
  317.         }
  318.        
  319.         bout.flush();
  320.         bout.close();
  321.        
  322.         String destFileScriptSql = sqlScriptName.replace(".sql", "_upgrade_"+versioneAttuale+".sql");
  323.        
  324.         FileSystemUtilities.writeFile(new File(sqlDestDir, destFileScriptSql), bout.toByteArray());
  325.        
  326.     }
  327.    
  328.     private static File _createSql_Aggiornamento(File sqlVersionSourceDir, File sqlDestDir, ByteArrayOutputStream bout , String nextVersion, String tipoDatabase,
  329.             boolean configurazioneUpgrade_runtime,
  330.             boolean configurazioneUpgrade_config,
  331.             boolean configurazioneUpgrade_tracce,
  332.             boolean configurazioneUpgrade_statistiche,
  333.             boolean configurazioneUpgrade_monitoraggio) throws Exception {
  334.                        
  335.         File sqlVersionSourceDirDatabase = new File(sqlVersionSourceDir, tipoDatabase);
  336.        
  337.         File[] files = sqlVersionSourceDirDatabase.listFiles();
  338.         if(files!=null && files.length>0) {
  339.            
  340.             boolean writeUpgrade = false;
  341.                        
  342.             Arrays.sort(files); // sono ordinati per data
  343.             for(File upgradeFile : files) {
  344.                
  345.                 if(upgradeFile.getName().contains("-runtimePdD-")) {
  346.                     // runtime
  347.                     if(!configurazioneUpgrade_runtime) {
  348.                         continue;
  349.                     }
  350.                 }
  351.                 else if(upgradeFile.getName().contains("-archiviComunicazioni-")) {
  352.                     // tracce
  353.                     if(!configurazioneUpgrade_tracce) {
  354.                         continue;
  355.                     }
  356.                 }
  357.                 else if(upgradeFile.getName().contains("-informazioniStatistiche-")) {
  358.                     // statistiche
  359.                     if(!configurazioneUpgrade_statistiche) {
  360.                         continue;
  361.                     }
  362.                 }
  363.                 else if(upgradeFile.getName().contains("-monitoraggio-")) {
  364.                     // monitoraggio
  365.                     if(!configurazioneUpgrade_monitoraggio) {
  366.                         continue;
  367.                     }
  368.                 }
  369.                 else {
  370.                     // configurazione (configurazionePdD, registroServizi)
  371.                     if(!configurazioneUpgrade_config) {
  372.                         continue;
  373.                     }
  374.                 }
  375.                
  376.                 if(writeUpgrade==false) {
  377.                     if(bout!=null){
  378.                         if(bout.size()>0){
  379.                             bout.write("\n\n".getBytes());
  380.                         }
  381.                         bout.write(("-- Upgrade to "+nextVersion).getBytes());
  382.                     }
  383.                     writeUpgrade = true;
  384.                 }
  385.                
  386.                 _createSqlAggiornamento(upgradeFile, bout);
  387.             }
  388.            
  389.         }
  390.        
  391.         File sqlVersionSourceDirInfoVersioneUpgrade = new File(sqlVersionSourceDir, "info-patch.sql");
  392.         if(sqlVersionSourceDirInfoVersioneUpgrade.exists()) {
  393.             return sqlVersionSourceDirInfoVersioneUpgrade;
  394.         }
  395.        
  396.         return null;
  397.     }
  398.    
  399.    
  400.     private static void _createSql(File sqlSourceDir,String sourceFile,File sqlDestDir, String destFile,
  401.             int prefix,ByteArrayOutputStream bout,
  402.             boolean splitDDL_DML) throws Exception{
  403.    
  404.         File src = new File(sqlSourceDir, sourceFile);
  405.         if(bout!=null){
  406.             byte[] b = FileSystemUtilities.readBytesFromFile(src);
  407.             if(bout.size()>0){
  408.                 bout.write("\n\n".getBytes());
  409.             }
  410.             bout.write(b);
  411.         }
  412.         else{
  413.             File dest = new File(sqlDestDir, parsePrefix(prefix)+destFile);
  414.             FileSystemUtilities.copy(src, dest);
  415.             if(splitDDL_DML){
  416.                 File destInit = new File(sqlDestDir, dest.getName().replace(".sql", "_init.sql"));
  417.                 splitFileForDDLtoDML(dest, dest, destInit);
  418.             }
  419.         }
  420.     }
  421.    
  422.     private static void _createSqlAggiornamento(File upgradeFile,ByteArrayOutputStream bout) throws Exception{
  423.         if(bout==null) {
  424.             throw new Exception("Param bout is null");
  425.         }
  426.         byte[] b = FileSystemUtilities.readBytesFromFile(upgradeFile);
  427.         if(bout.size()>0){
  428.             bout.write("\n\n".getBytes());
  429.         }
  430.         bout.write(b);
  431.     }
  432.    
  433.     private static String parsePrefix(int prefix){
  434.         if(prefix<10){
  435.             return "0"+prefix+"_";
  436.         }
  437.         else{
  438.             return prefix+"_";
  439.         }
  440.     }
  441.    
  442.     private static void splitFileForDDLtoDML(File sqlFile,File sqlFileDest,File sqlFileInitDest) throws Exception{
  443.        
  444.         boolean dmlOpen = false;
  445.        
  446.         ByteArrayOutputStream boutDDL = new ByteArrayOutputStream();
  447.         ByteArrayOutputStream boutDML = new ByteArrayOutputStream();
  448.        
  449.         BufferedReader br = null;
  450.         try {
  451.             br = new BufferedReader(new FileReader(sqlFile));
  452.             String line;
  453.             while ((line = br.readLine()) != null) {
  454.                // process the line.
  455.                
  456.                 if(dmlOpen){
  457.                     boutDML.write(line.getBytes());
  458.                     boutDML.write("\n".getBytes());
  459.                     if(line.contains(";")){
  460.                         dmlOpen = false; // finish
  461.                     }
  462.                 }
  463.                 else{
  464.                     if(isDML(line)){
  465.                         dmlOpen = true; // start
  466.                         boutDML.write(line.getBytes());
  467.                         boutDML.write("\n".getBytes());
  468.                         if(line.contains(";")){
  469.                             dmlOpen = false; // finish (in una unica riga)
  470.                         }
  471.                     }
  472.                     else{
  473.                         boutDDL.write(line.getBytes());
  474.                         boutDDL.write("\n".getBytes());
  475.                     }
  476.                 }
  477.                
  478.             }
  479.         }finally {
  480.             try {
  481.                 if(br!=null)
  482.                     br.close();
  483.             }catch(Throwable t) {
  484.                 // ignore
  485.             }
  486.         }
  487.        
  488.         //System.out.println("DDL["+boutDDL.size()+"] DML["+boutDML.size()+"]");
  489.        
  490.         if(boutDDL.size()>0){
  491.             FileSystemUtilities.writeFile(sqlFileDest, boutDDL.toByteArray());
  492.         }
  493.         if(boutDML.size()>0){
  494.             FileSystemUtilities.writeFile(sqlFileInitDest, boutDML.toByteArray());
  495.         }
  496.        
  497.     }
  498.     private static boolean isDML(String line){
  499.        
  500.         String tmp = new String(line);
  501.         tmp = tmp.trim().toLowerCase();
  502.        
  503.         if(tmp.startsWith("insert ")){
  504.            
  505.             // check hsql, es: INSERT INTO db_info_init_seq VALUES (NEXT VALUE FOR seq_db_info);
  506.             if(tmp.contains("_init_seq ") && tmp.contains("next value ") ){
  507.                 return false;

  508.             }
  509.            
  510.             // insert on tracce_ext_protocol_info
  511.             if(tmp.contains("insert on ")){
  512.                 return false;
  513.             }
  514.            
  515.             return true;
  516.         }
  517.         else if(tmp.startsWith("update ")){
  518.            
  519.             return true;
  520.            
  521.         }
  522.         else if(tmp.startsWith("delete ")){
  523.            
  524.             // ON DELETE CASCADE
  525.             if(tmp.contains("on delete cascade")){
  526.                 return false;
  527.             }
  528.            
  529.             return true;
  530.            
  531.         }
  532.         return false;
  533.        
  534.     }
  535.    
  536. }