SavedMessage.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.pdd.core;

  21. import java.io.ByteArrayInputStream;
  22. import java.io.File;
  23. import java.io.FileInputStream;
  24. import java.io.FileNotFoundException;
  25. import java.io.FileOutputStream;
  26. import java.io.InputStream;
  27. import java.nio.file.Files;
  28. import java.sql.Connection;
  29. import java.sql.PreparedStatement;
  30. import java.sql.ResultSet;
  31. import java.sql.SQLException;
  32. import java.sql.Timestamp;
  33. import java.util.Date;

  34. import org.openspcoop2.generic_project.exception.DeserializerException;
  35. import org.openspcoop2.message.OpenSPCoop2Message;
  36. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  37. import org.openspcoop2.message.OpenSPCoop2MessageParseResult;
  38. import org.openspcoop2.message.constants.MessageRole;
  39. import org.openspcoop2.message.constants.MessageType;
  40. import org.openspcoop2.message.context.MessageContext;
  41. import org.openspcoop2.message.context.SerializedContext;
  42. import org.openspcoop2.message.context.SerializedParameter;
  43. import org.openspcoop2.message.exception.MessageException;
  44. import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
  45. import org.openspcoop2.pdd.core.state.IOpenSPCoopState;
  46. import org.openspcoop2.pdd.core.state.OpenSPCoopStateful;
  47. import org.openspcoop2.pdd.core.state.OpenSPCoopStateless;
  48. import org.openspcoop2.protocol.engine.constants.Costanti;
  49. import org.openspcoop2.protocol.sdk.Context;
  50. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  51. import org.openspcoop2.protocol.sdk.state.RequestInfoConfigUtilities;
  52. import org.openspcoop2.protocol.sdk.state.StateMessage;
  53. import org.openspcoop2.utils.LoggerWrapperFactory;
  54. import org.openspcoop2.utils.UtilsException;
  55. import org.openspcoop2.utils.beans.WriteToSerializerType;
  56. import org.openspcoop2.utils.io.notifier.NotifierInputStreamParams;
  57. import org.openspcoop2.utils.jdbc.IJDBCAdapter;
  58. import org.openspcoop2.utils.serialization.JavaDeserializer;
  59. import org.slf4j.Logger;


  60. /**
  61.  * Classe utilizzata per rappresentare un messaggio Soap nel contesto della libreria.
  62.  *
  63.  * @author Poli Andrea (apoli@link.it)
  64.  * @author Tronci Fabio (tronci@link.it)
  65.  * @author Lorenzo Nardi (nardi@link.it)
  66.  * @author $Author$
  67.  * @version $Rev$, $Date$
  68.  */



  69. public class SavedMessage implements java.io.Serializable {

  70.     /**
  71.      * serialVersionUID
  72.      */
  73.     private static final long serialVersionUID = 1L;

  74.     /** Logger utilizzato per debug. */
  75.     protected transient Logger internalLog = null;
  76.     private synchronized void initLog() {
  77.         if(this.internalLog==null) {
  78.             this.internalLog = LoggerWrapperFactory.getLogger(SavedMessage.class);
  79.         }
  80.     }
  81.     protected Logger getLog() {
  82.         if(this.internalLog==null) {
  83.             this.initLog();
  84.         }
  85.         return this.internalLog;
  86.     }

  87.     public static final String REST_CONTENT_TYPE_EMPTY = "____EMPTY____";
  88.    
  89.     private static final String MSG_BYTES = "_bytes.bin";
  90.     private static final String MSG_CONTEXT = "_context.bin";
  91.     private static final String MSG_RESPONSE_BYTES = "_response_bytes.bin";
  92.     private static final String MSG_RESPONSE_CONTEXT = "_response_context.bin";
  93.     private static final String MSG_TRANSACTION_CONTEXT = "_transaction_context.bin";


  94.     /* ********  F I E L D S  P R I V A T I  ******** */

  95.     /** Identificativo del Messaggio */
  96.     protected String idMessaggio;
  97.     /** Indicazione se il messaggio sara' salvato nella INBOX dei messaggi, o nella OUTBOX */
  98.     protected String box;
  99.     /** Indicazione se il messaggio deve essere registrato su file System o su DB */
  100.     protected boolean saveOnFS;
  101.     /** Identificativo del Messaggio passato sotto una funziona HASH */
  102.     protected String keyMsgBytes;
  103.     /** Identificativo del MessaggeContext passato sotto una funziona HASH */
  104.     protected String keyMsgContext;
  105.     /** Indica la directory dove effettuare salvataggi */
  106.     /** Identificativo del Messaggio passato sotto una funziona HASH */
  107.     protected String keyMsgResponseBytes;
  108.     /** Identificativo del MessageContext passato sotto una funziona HASH */
  109.     protected String keyMsgResponseContext;
  110.     /** Identificativo del TransactionContext passato sotto una funziona HASH */
  111.     protected String keyMsgTransactionContext;
  112.     /** Indica la directory dove effettuare salvataggi */
  113.     private String workDir;
  114.     /** AdapterJDBC */
  115.     protected transient IJDBCAdapter adapter;


  116.     protected transient IOpenSPCoopState openspcoopstate;

  117.     /** OpenSPCoopProperties */
  118.     private transient OpenSPCoop2Properties openspcoopProperties = OpenSPCoop2Properties.getInstance();




  119.     /* ********  C O S T R U T T O R E  ******** */
  120.     /**
  121.      * Costruttore.
  122.      *
  123.      * @param idMsg ID del Messaggio
  124.      * @param openspcoopstate state Oggetto che rappresenta lo stato di una busta
  125.      * @param box Indicazione se il messaggio sara' salvato nella INBOX dei messaggi, o nella OUTBOX
  126.      * @param workDir Directory dove effettuare salvataggi se il messaggio deve essere registrato su FileSystem, null se il messaggio deve essere registrato su DB
  127.      *
  128.      */
  129.     public SavedMessage(String idMsg, IOpenSPCoopState openspcoopstate, String box, String workDir,Logger alog) throws UtilsException{
  130.         this(idMsg, openspcoopstate ,box,workDir,null,alog);
  131.     }

  132.     /**
  133.      * Costruttore.
  134.      *
  135.      * @param idMsg ID del Messaggio
  136.      * @param openspcoopstate state Oggetto che rappresenta lo stato di una busta
  137.      * @param box Indicazione se il messaggio sara' salvato nella INBOX dei messaggi, o nella OUTBOX
  138.      * @param adapterJDBC  JDBCAdapter se il messaggio deve essere registrato su DB, null se il messaggio deve essere registrato su file System
  139.      *
  140.      */
  141.     public SavedMessage(String idMsg, IOpenSPCoopState openspcoopstate, String box, IJDBCAdapter adapterJDBC,Logger alog) throws UtilsException{
  142.         this(idMsg, openspcoopstate ,box,null,adapterJDBC,alog);
  143.     }


  144.     /**
  145.      * Costruttore.
  146.      *
  147.      * @param idMsg ID del Messaggio
  148.      * @param openspcoopstate state Oggetto che rappresenta lo stato di una busta
  149.      * @param box Indicazione se il messaggio sara' salvato nella INBOX dei messaggi, o nella OUTBOX
  150.      * @param workDir Directory dove effettuare salvataggi se il messaggio deve essere registrato su FileSystem, null se il messaggio deve essere registrato su DB
  151.      * @param adapterJDBC  JDBCAdapter se il messaggio deve essere registrato su DB, null se il messaggio deve essere registrato su file System
  152.      *
  153.      */
  154.     public SavedMessage(String idMsg, IOpenSPCoopState openspcoopstate, String box, String workDir,
  155.             IJDBCAdapter adapterJDBC,Logger alog) throws UtilsException{
  156.         this.idMessaggio = idMsg;
  157.         this.box = box;
  158.         this.openspcoopstate = openspcoopstate;
  159.         if(alog!=null){
  160.             this.internalLog = alog;
  161.         }else{
  162.             this.internalLog = LoggerWrapperFactory.getLogger(SavedMessage.class);
  163.         }
  164.         try{

  165.             String hashKey = this.hash(idMsg);
  166.             if(hashKey == null){
  167.                 throw new UtilsException("Codifica hash non riuscita: keyMsgBytes is null");
  168.             }
  169.            
  170.             this.keyMsgBytes = hashKey + MSG_BYTES;
  171.             this.keyMsgResponseBytes = hashKey + MSG_RESPONSE_BYTES;

  172.             this.keyMsgContext = hashKey + MSG_CONTEXT;
  173.             this.keyMsgResponseContext = hashKey + MSG_RESPONSE_CONTEXT;
  174.            
  175.             this.keyMsgTransactionContext = hashKey + MSG_TRANSACTION_CONTEXT;

  176.         }catch(Exception e){
  177.             String errorMsg = "SOAP_MESSAGE, costructor error (CodificaHash): "+box+"/"+idMsg+": "+e.getMessage();      
  178.             this.getLog().error(errorMsg);
  179.             throw new UtilsException(errorMsg,e);
  180.         }

  181.         if(adapterJDBC==null){
  182.             this.saveOnFS = true;
  183.             this.workDir = workDir;
  184.         }else{
  185.             this.saveOnFS = false;
  186.             this.adapter = adapterJDBC;
  187.         }
  188.     }

  189.     /**
  190.      * Ritorna un intero che rappresenta la chiave di una stringa.
  191.      *
  192.      * @param key Stringa su cui effettuare la traduzione.
  193.      * @return hash della stringa.
  194.      *
  195.      */
  196.     private String hash(String key) throws UtilsException{
  197.         try{
  198.             StringBuilder returnKey = new StringBuilder();
  199.             for(int i=0; i<key.length();i++){
  200.                 if( (key.charAt(i) != '_') && (key.charAt(i) != '-') &&
  201.                         (key.charAt(i) != '.') && (key.charAt(i) != ':') )
  202.                     returnKey.append(key.charAt(i));
  203.             }

  204.             return returnKey.toString();

  205.         } catch (java.lang.Exception e) {
  206.             throw new UtilsException("Utilities.hash error "+e.getMessage(),e);
  207.         }
  208.     }








  209.     /* ********  U T I L I T Y  ******** */

  210.     /**
  211.      * Ritorna la directory base su cui effettuare salvataggi
  212.      *
  213.      * @return Ritorna la directory base su cui effettuare salvataggi
  214.      *
  215.      */
  216.     public String getBaseDir() throws UtilsException{

  217.         String prefix = "SOAP_MESSAGE, getBaseDir: "+this.box+"/"+this.idMessaggio;
  218.        
  219.         // Controllo esistenza directory fornita per salvare i messaggi
  220.         File dir = new File(this.workDir);
  221.         if(!dir.exists()){
  222.             String errorMsg = prefix+": directory di lavoro inesistente ("+this.workDir+").";      
  223.             this.getLog().error(errorMsg);
  224.             throw new UtilsException(errorMsg);
  225.         }
  226.         String baseDir = this.workDir;
  227.         if (!baseDir.endsWith(File.separator))
  228.             baseDir = baseDir + File.separator;

  229.         // Seleziono INBOX/OUTBOX
  230.         if(Costanti.INBOX.equals(this.box)){
  231.             baseDir = baseDir + Costanti.INBOX;
  232.         }else if (Costanti.OUTBOX.equals(this.box)){
  233.             baseDir = baseDir + Costanti.OUTBOX;
  234.         }else{
  235.             String errorMsg = prefix+": box non valido? .";    
  236.             this.getLog().error(errorMsg);
  237.             throw new UtilsException(errorMsg);
  238.         }

  239.         // Controllo esistenza di INBUX/OUTBOX
  240.         File dirINOUT = new File(baseDir);
  241.         if(!dirINOUT.exists() &&
  242.             !dirINOUT.mkdir()){
  243.             String errorMsg = prefix+": directory di lavoro ("+this.workDir+") non permette la creazione di sottodirectory INBOX/OUTBOX.";      
  244.             this.getLog().error(errorMsg);
  245.             throw new UtilsException(errorMsg);
  246.         }

  247.         return (baseDir+ File.separator);

  248.     }

  249.     /**
  250.      * Ritorna il codice del Messaggio
  251.      *
  252.      * @return Codice.
  253.      *
  254.      */
  255.     public String getIdMessaggio(){
  256.         return this.idMessaggio;
  257.     }

  258.     /**
  259.      *Aggiorna lo stato
  260.      */
  261.     public void updateState(IOpenSPCoopState openspcoopstate){
  262.         this.openspcoopstate = openspcoopstate;
  263.     }
  264.    
  265.     protected void checkInizializzazioneWorkingDir(String saveDir) throws UtilsException {
  266.         if(saveDir==null){
  267.             String errorMsg = "WorkDir non correttamente inizializzata";        
  268.             throw new UtilsException(errorMsg);
  269.         }
  270.     }
  271.    
  272.     protected void checkInizializzazioneAdapter() throws UtilsException {
  273.         if(this.adapter==null) {
  274.             throw new UtilsException("Adapter unavailable");
  275.         }
  276.     }
  277.    
  278.     protected void logError(String errorMsg, Exception e) {
  279.         this.getLog().error(errorMsg,e);
  280.     }
  281.    
  282.    


  283.     /* ********  S A V E  ******** */

  284.     /**
  285.      * Dato un messaggio come parametro, si occupa di salvarlo nel filesystem/DB.
  286.      * Il SoapEnvelope viene salvato nel FileSystem associandoci l'informazione strutturale <var>idMessaggio</var>.
  287.      *
  288.      *
  289.      * @param msg Messaggio.
  290.      *
  291.      */
  292.     public void save(OpenSPCoop2Message msg, boolean isRichiesta, boolean portaDiTipoStateless, boolean consumeMessage, Timestamp oraRegistrazione) throws UtilsException{
  293.         SavedMessagePSUtilities.save(this, msg, isRichiesta, portaDiTipoStateless, consumeMessage, oraRegistrazione);
  294.     }    
  295.     protected void saveMessageBytes(String path,OpenSPCoop2Message msg, boolean consumeMessage, boolean overwrite) throws UtilsException{

  296.         FileOutputStream fos = null;
  297.         try{

  298.             File fileMsg = new File(path);
  299.             if(fileMsg.exists()){
  300.                 if(overwrite) {
  301.                     deleteMessageFile(fileMsg);
  302.                 }
  303.                 else {
  304.                     throw new UtilsException("L'identificativo del Messaggio risulta già registrato: "+path);
  305.                 }
  306.             }  

  307.             fos = new FileOutputStream(path);
  308.             // Scrittura Messaggio su FileSystem
  309.             msg.writeTo(fos,consumeMessage);
  310.             fos.close();

  311.         }catch(Exception e){
  312.             try{
  313.                 if( fos != null )
  314.                     fos.close();
  315.             } catch(Exception er) {
  316.                 // close
  317.             }
  318.             throw new UtilsException("Utilities.saveMessage error "+e.getMessage(),e);
  319.         }
  320.     }
  321.     protected void saveMessageContext(String path,OpenSPCoop2Message msg, boolean overwrite) throws UtilsException{

  322.         FileOutputStream fos = null;
  323.         try{

  324.             File fileMsg = new File(path);
  325.             if(fileMsg.exists()){
  326.                 if(overwrite) {
  327.                     deleteMessageFile(fileMsg);
  328.                 }
  329.                 else {
  330.                     throw new UtilsException("L'identificativo del Messaggio risulta gia' registrato: "+path);
  331.                 }
  332.             }  

  333.             fos = new FileOutputStream(path);
  334.             // Scrittura Messaggio su FileSystem
  335.             msg.serializeResourcesTo(fos);
  336.             fos.close();

  337.         }catch(Exception e){
  338.             try{
  339.                 if( fos != null )
  340.                     fos.close();
  341.             } catch(Exception er) {
  342.                 // close
  343.             }
  344.             throw new UtilsException("Utilities.saveMessageContext error "+e.getMessage(),e);
  345.         }
  346.     }
  347.     protected void saveTransactionContext(String path,SerializedContext sc, boolean overwrite) throws UtilsException{

  348.         FileOutputStream fos = null;
  349.         try{

  350.             File fileMsg = new File(path);
  351.             if(fileMsg.exists()){
  352.                 if(overwrite) {
  353.                     deleteMessageFile(fileMsg);
  354.                 }
  355.                 else {
  356.                     throw new UtilsException("L'identificativo del Messaggio risulta gia' registrato: "+path);
  357.                 }
  358.             }  

  359.             fos = new FileOutputStream(path);
  360.             // Scrittura Messaggio su FileSystem
  361.             sc.writeTo(fos, WriteToSerializerType.XML_JAXB);
  362.             fos.close();

  363.         }catch(Exception e){
  364.             try{
  365.                 if( fos != null )
  366.                     fos.close();
  367.             } catch(Exception er) {
  368.                 // close
  369.             }
  370.             throw new UtilsException("Utilities.saveTransactionContext error "+e.getMessage(),e);
  371.         }
  372.     }

  373.    
  374.     public void updateResponse(OpenSPCoop2Message msg, boolean consumeMessage) throws UtilsException{
  375.         SavedMessagePSUtilities.updateResponse(this, msg, consumeMessage);
  376.     }
  377.    
  378.     public void updateTransactionContext(Context transactionContext) throws UtilsException{
  379.         RequestInfo requestInfoBackup = null;
  380.         java.util.Map<String,Object> dynamicContext = null;
  381.         try {
  382.             if(transactionContext!=null) {
  383.                 requestInfoBackup = RequestInfoConfigUtilities.normalizeRequestInfoBeforeSerialization(transactionContext);
  384.                 dynamicContext = org.openspcoop2.core.constants.Costanti.removeDynamicMap(transactionContext);
  385.             }
  386.             SavedMessagePSUtilities.updateTransactionContext(this, transactionContext);
  387.         }finally {
  388.             if(requestInfoBackup!=null) {
  389.                 RequestInfoConfigUtilities.restoreRequestInfoAfterSerialization(transactionContext, requestInfoBackup);
  390.             }
  391.             if(dynamicContext!=null) {
  392.                 transactionContext.put(org.openspcoop2.core.constants.Costanti.DYNAMIC_MAP_CONTEXT, dynamicContext);
  393.             }
  394.         }
  395.     }
  396.    
  397.     private void deleteMessageFile(File fileMsg) throws UtilsException {
  398.         try {
  399.             Files.delete(fileMsg.toPath());
  400.         }catch(Exception e) {
  401.             throw new UtilsException("L'identificativo del Messaggio risulta già registrato e non eliminabile ("+fileMsg.getAbsolutePath()+"): "+e.getMessage(),e);
  402.         }
  403.     }



  404.     /* ********  R E A D  ******** */

  405.     /**
  406.      * Ritorna un messaggio che era stata precedentemente salvata nel filesystem/DB.
  407.      *
  408.      * @return il messaggio precedentemente salvato
  409.      *
  410.      */
  411.     public OpenSPCoop2Message read(boolean isRichiesta, boolean portaDiTipoStateless, Date oraRegistrazione) throws UtilsException {
  412.          return readEngine(isRichiesta, portaDiTipoStateless, oraRegistrazione, false, true, null);
  413.     }
  414.     public OpenSPCoop2Message readResponse(Date oraRegistrazione, boolean throwExceptionIfNotExists) throws UtilsException {
  415.          return readEngine(false, false, oraRegistrazione, true, throwExceptionIfNotExists, null);
  416.     }
  417.     public Context readTransactionContext(Date oraRegistrazione) throws UtilsException {
  418.         Context c = new Context();
  419.         readEngine(false, false, oraRegistrazione, false, true, c);
  420.         return c;
  421.     }
  422.     private OpenSPCoop2Message readEngine(boolean isRichiesta, boolean portaDiTipoStateless, Date oraRegistrazione, boolean readResponseField, boolean throwExceptionIfNotExists, Context readTransactionContext) throws UtilsException {

  423.         if( !portaDiTipoStateless ) {

  424.             Connection connectionDB = (isRichiesta) ?
  425.                     ((StateMessage)this.openspcoopstate.getStatoRichiesta()).getConnectionDB() :
  426.                         ((StateMessage)this.openspcoopstate.getStatoRisposta()).getConnectionDB();

  427.             return readMessage(oraRegistrazione, readResponseField, throwExceptionIfNotExists, readTransactionContext, connectionDB);

  428.         }else { /** if ( portaDiTipoStateless ){ */
  429.             if (isRichiesta) return ((OpenSPCoopStateless)this.openspcoopstate).getRichiestaMsg();
  430.             else return ((OpenSPCoopStateless)this.openspcoopstate).getRispostaMsg();
  431.         }
  432.     }

  433.     private OpenSPCoop2Message readMessage(Date oraRegistrazione, boolean readResponseField, boolean throwExceptionIfNotExists, Context readTransactionContext, Connection connectionDB) throws UtilsException {
  434.        
  435.         if(readTransactionContext!=null && this.saveOnFS) {
  436.             fillTransactionContextFromFileSystem(readTransactionContext, true); // il transactionContext deve esistere sempre
  437.             return null;    
  438.         }
  439.        
  440.         OpenSPCoop2Message msg = null;
  441.         PreparedStatement pstmt = null;
  442.         ResultSet rs = null;
  443.         try{

  444.             String sql = buildReadStatement(oraRegistrazione, readResponseField, readTransactionContext);
  445.            
  446.             pstmt =  connectionDB.prepareStatement(sql);
  447.             initPreparedStatement(oraRegistrazione, pstmt);
  448.             rs = pstmt.executeQuery();
  449.            
  450.             msg = readMessage(rs, readResponseField, throwExceptionIfNotExists, readTransactionContext);

  451.             rs.close();
  452.             pstmt.close();

  453.         }catch(Exception e){
  454.             try{
  455.                 if( rs != null )
  456.                     rs.close();
  457.             } catch(Exception er) {
  458.                 // close
  459.             }
  460.             try{
  461.                 if( pstmt != null )
  462.                     pstmt.close();
  463.             } catch(Exception er) {
  464.                 // close
  465.             }
  466.             String errorMsg = "SOAP_MESSAGE, read: "+this.box+"/"+this.idMessaggio+": "+e.getMessage();    
  467.             logError(errorMsg, e);
  468.             throw new UtilsException(errorMsg,e);
  469.         }
  470.        
  471.         return msg;
  472.     }
  473.    
  474.     private void fillTransactionContextFromFileSystem(Context readTransactionContext, boolean throwExceptionIfNotExists) throws UtilsException {
  475.         String saveDir = getBaseDir();
  476.         checkInizializzazioneWorkingDir(saveDir);
  477.        
  478.         InputStream isContext = null;
  479.         try{
  480.        
  481.             // Lettura Message Context
  482.             isContext = readTransactionContextBytes(saveDir, throwExceptionIfNotExists, null);
  483.                                
  484.             // CostruzioneMessaggio
  485.             if(isContext!=null) {
  486.                 fillTransactionContext(readTransactionContext, isContext);
  487.             }
  488.            
  489.         }catch(Exception e){
  490.             try{
  491.                 if( isContext != null )
  492.                     isContext.close();
  493.             } catch(Exception er) {
  494.                 // close
  495.             }
  496.             throw new UtilsException(e.getMessage(),e);
  497.         }
  498.        
  499.     }
  500.    
  501.     private String buildReadStatement(Date oraRegistrazione, boolean readResponseField, Context readTransactionContext) {
  502.         StringBuilder query = new StringBuilder();
  503.         if(readTransactionContext!=null) {
  504.             query.append("select TRANSACTION_CONTEXT ");
  505.         }
  506.         else {
  507.             String columnContentType = readResponseField ? "RESPONSE_CONTENT_TYPE" : "CONTENT_TYPE";
  508.             String columnMsgBytes = readResponseField ? "RESPONSE_MSG_BYTES" : "MSG_BYTES";
  509.             String columnMsgContext = readResponseField ? "RESPONSE_MSG_CONTEXT" : "MSG_CONTEXT";
  510.            
  511.             // Leggo proprieta' messaggio
  512.             if(this.saveOnFS)
  513.                 query.append("select "+columnContentType+" ");
  514.             else
  515.                 query.append("select "+columnContentType+","+columnMsgBytes+","+columnMsgContext+" ");
  516.         }
  517.         query.append("from ");
  518.         query.append(GestoreMessaggi.DEFINIZIONE_MESSAGGI);
  519.         query.append(" WHERE ");
  520.         if(oraRegistrazione!=null) {
  521.             query.append("(ORA_REGISTRAZIONE BETWEEN ? AND ?) AND ");
  522.         }
  523.         query.append("ID_MESSAGGIO = ? AND TIPO = ?");
  524.        
  525.         return query.toString();
  526.     }
  527.    
  528.     private void initPreparedStatement(Date oraRegistrazione, PreparedStatement pstmt) throws SQLException {
  529.         int index = 1;
  530.        
  531.         Timestamp leftValue = null;
  532.         Timestamp rightValue = null;
  533.         if(oraRegistrazione!=null) {
  534.             leftValue = new Timestamp(oraRegistrazione.getTime() - (1000*60*5));
  535.             rightValue = new Timestamp(oraRegistrazione.getTime() + (1000*60*5));
  536.             pstmt.setTimestamp(index++,leftValue);
  537.             pstmt.setTimestamp(index++,rightValue);
  538.         }
  539.        
  540.         pstmt.setString(index++,this.idMessaggio);
  541.         if(Costanti.INBOX.equals(this.box))
  542.             pstmt.setString(index,Costanti.INBOX);
  543.         else
  544.             pstmt.setString(index,Costanti.OUTBOX);
  545.     }
  546.    
  547.     private InputStream readMessageBytes(String contentType, String saveDir, boolean readResponseField, ResultSet rs) throws UtilsException, FileNotFoundException, SQLException {
  548.         if(contentType!=null && !"".equals(contentType)) {
  549.             if(this.saveOnFS){
  550.                 // READ FROM FILE SYSTEM
  551.                 String pathBytes = saveDir + (readResponseField ? this.keyMsgResponseBytes : this.keyMsgBytes);
  552.                 File fileCheckBytes = new File(pathBytes);
  553.                 if(!fileCheckBytes.exists()){
  554.                     String errorMsg = "Il messaggio non risulta gia' registrato ("+pathBytes+").";      
  555.                     throw new UtilsException(errorMsg);
  556.                 }      
  557.                 return new FileInputStream(pathBytes);
  558.             }else{
  559.                 // READ FROM DB
  560.                 this.checkInizializzazioneAdapter();
  561.                 return new java.io.ByteArrayInputStream(this.adapter.getBinaryData(rs,2));
  562.             }
  563.         }
  564.         return null;
  565.     }

  566.     private InputStream readBytesCheckNullable(String tipo, File fileCheckContext, boolean throwExceptionIfNotExists) throws UtilsException, FileNotFoundException {
  567.         if(!fileCheckContext.exists()){
  568.             if(throwExceptionIfNotExists) {
  569.                 String errorMsg = "Il messaggio ("+tipo+") non risulta gia' registrato ("+fileCheckContext.getAbsolutePath()+").";      
  570.                 throw new UtilsException(errorMsg);
  571.             }
  572.             else {
  573.                 return null;
  574.             }
  575.         }
  576.         return new FileInputStream(fileCheckContext);
  577.     }
  578.     private InputStream readBytesCheckNullable(String tipo, byte[]content, boolean throwExceptionIfNotExists) throws UtilsException {
  579.         if(content==null) {
  580.             if(throwExceptionIfNotExists) {
  581.                 String errorMsg = "Il messaggio ("+tipo+") non risulta gia' registrato.";      
  582.                 throw new UtilsException(errorMsg);
  583.             }
  584.             else {
  585.                 return null;
  586.             }
  587.         }
  588.         return new java.io.ByteArrayInputStream(content);
  589.     }
  590.    
  591.     private InputStream readContextBytes(String saveDir, boolean readResponseField, boolean throwExceptionIfNotExists, ResultSet rs) throws UtilsException, FileNotFoundException, SQLException {
  592.         if(this.saveOnFS){
  593.             // READ FROM FILE SYSTEM
  594.             String pathContext = saveDir + (readResponseField ? this.keyMsgResponseContext : this.keyMsgContext);
  595.             File fileCheckContext = new File(pathContext);
  596.             return readBytesCheckNullable("context", fileCheckContext, throwExceptionIfNotExists) ;
  597.         }else{
  598.             // READ FROM DB
  599.             this.checkInizializzazioneAdapter();
  600.             byte[]content = this.adapter.getBinaryData(rs,3);
  601.             return readBytesCheckNullable("context", content, throwExceptionIfNotExists);
  602.         }
  603.     }
  604.    
  605.     private InputStream readTransactionContextBytes(String saveDir, boolean throwExceptionIfNotExists, ResultSet rs) throws UtilsException, FileNotFoundException, SQLException {
  606.         if(this.saveOnFS){
  607.             // READ FROM FILE SYSTEM
  608.             String pathContext = saveDir + this.keyMsgTransactionContext;
  609.             File fileCheckContext = new File(pathContext);
  610.             return readBytesCheckNullable("transaction context", fileCheckContext, throwExceptionIfNotExists) ;
  611.         }else{
  612.             // READ FROM DB
  613.             this.checkInizializzazioneAdapter();
  614.             byte[]content = this.adapter.getBinaryData(rs,1);
  615.             return readBytesCheckNullable("transaction context", content, throwExceptionIfNotExists);
  616.         }
  617.     }
  618.    
  619.     private OpenSPCoop2Message readMessage(ResultSet rs, boolean readResponseField, boolean throwExceptionIfNotExists, Context readTransactionContext) throws UtilsException, SQLException {
  620.         if(rs==null){
  621.             String errorMsg = "ResultSet is null?";    
  622.             throw new UtilsException(errorMsg);
  623.         }
  624.         if(!rs.next()){
  625.             String errorMsg = "Messaggio non esistente";        
  626.             throw new UtilsException(errorMsg);
  627.         }

  628.         OpenSPCoop2Message msg = null;
  629.         if(readTransactionContext!=null) {
  630.             fillTransactionContext(rs, readTransactionContext, true); // il transactionContext deve esistere sempre
  631.         }
  632.         else {
  633.             msg = readMessage(rs, readResponseField, throwExceptionIfNotExists);
  634.         }
  635.         return msg;
  636.     }
  637.    
  638.     private void fillTransactionContext(ResultSet rs, Context readTransactionContext, boolean throwExceptionIfNotExists) throws UtilsException {
  639.         InputStream isContext = null;
  640.         try{
  641.        
  642.             // Lettura Message Context
  643.             isContext = readTransactionContextBytes(null, throwExceptionIfNotExists, rs);
  644.                                
  645.             // CostruzioneMessaggio
  646.             if(isContext!=null) {
  647.                 fillTransactionContext(readTransactionContext, isContext);
  648.             }
  649.            
  650.         }catch(Exception e){
  651.             try{
  652.                 if( isContext != null )
  653.                     isContext.close();
  654.             } catch(Exception er) {
  655.                 // close
  656.             }
  657.             throw new UtilsException(e.getMessage(),e);
  658.         }
  659.     }
  660.    
  661.     private OpenSPCoop2Message readMessage(ResultSet rs, boolean readResponseField, boolean throwExceptionIfNotExists) throws UtilsException, SQLException {
  662.         String saveDir = null;
  663.         if(this.saveOnFS){
  664.             // READ FROM FILE SYSTEM
  665.            
  666.             saveDir = getBaseDir();
  667.             checkInizializzazioneWorkingDir(saveDir);
  668.         }
  669.        
  670.         InputStream isBytes = null;
  671.         InputStream isContext = null;
  672.         try{
  673.        
  674.             // Lettura Message Context
  675.             isContext = readContextBytes(saveDir, readResponseField, throwExceptionIfNotExists, rs);
  676.             if(isContext==null) {
  677.                 // viene lanciata una eccezione prima se throwExceptionIfNotExists
  678.                 return null;
  679.             }
  680.            
  681.             // ContentType
  682.             String columnContentType = readResponseField ? "RESPONSE_CONTENT_TYPE" : "CONTENT_TYPE";
  683.             String contentType = rs.getString(columnContentType);
  684.            
  685.             // Costruzione MessageContext
  686.             SavedMessageContext smc = buildMessageContext(contentType, isContext);
  687.             contentType = smc.contentTypeNormalized;
  688.            
  689.             // Lettura Message Bytes
  690.             isBytes = readMessageBytes(contentType, saveDir, readResponseField, rs);
  691.                
  692.             // CostruzioneMessaggio
  693.             return buildMessage(smc, contentType, isBytes);
  694.            
  695.         }catch(Exception e){
  696.             try{
  697.                 if( isBytes != null )
  698.                     isBytes.close();
  699.             } catch(Exception er) {
  700.                 // close
  701.             }
  702.             try{
  703.                 if( isContext != null )
  704.                     isContext.close();
  705.             } catch(Exception er) {
  706.                 // close
  707.             }
  708.             throw new UtilsException(e.getMessage(),e);
  709.         }
  710.     }
  711.    
  712.     private SavedMessageContext buildMessageContext(String contentType, InputStream isContext) throws UtilsException, DeserializerException {
  713.         org.openspcoop2.message.context.utils.serializer.JaxbDeserializer jaxbDeserializer  =
  714.                 new org.openspcoop2.message.context.utils.serializer.JaxbDeserializer();
  715.         MessageContext msgContext = jaxbDeserializer.readMessageContext(isContext);
  716.        
  717.         if(msgContext.getMessageType()==null) {
  718.             throw new UtilsException("Message Type undefined in context serialized");
  719.         }
  720.         MessageType mt = MessageType.valueOf(msgContext.getMessageType());
  721.         if(mt==null) {
  722.             throw new UtilsException("MessageType ["+msgContext.getMessageType()+"] unknown");
  723.         }
  724.        
  725.         if(msgContext.getMessageRole()==null) {
  726.             throw new UtilsException("Message Role undefined in context serialized");
  727.         }
  728.         MessageRole mr = MessageRole.valueOf(msgContext.getMessageRole());
  729.         if(mr==null) {
  730.             throw new UtilsException("MessageRole ["+msgContext.getMessageRole()+"] unknown");
  731.         }
  732.        
  733.         if(MessageType.BINARY.equals(mt) &&
  734.                 REST_CONTENT_TYPE_EMPTY.equals(contentType)) {
  735.             contentType = null;
  736.         }
  737.        
  738.         SavedMessageContext smc = new SavedMessageContext();
  739.         smc.msgContext = msgContext;
  740.         smc.mt = mt;
  741.         smc.mr = mr;
  742.         smc.contentTypeNormalized = contentType;
  743.         return smc;
  744.     }
  745.    
  746.     private OpenSPCoop2Message buildMessage(SavedMessageContext smc, String contentType, InputStream isBytes) throws MessageException {
  747.        
  748.         OpenSPCoop2MessageFactory mf = OpenSPCoop2MessageFactory.getDefaultMessageFactory();
  749.         NotifierInputStreamParams notifierInputStreamParams = null; // Non dovrebbe servire, un eventuale handler attaccato, dovrebbe gia aver ricevuto tutto il contenuto una volta serializzato il messaggio su database.
  750.         OpenSPCoop2MessageParseResult pr = null;
  751.         pr = mf.createMessage(smc.mt,smc.mr,contentType,
  752.                 isBytes,notifierInputStreamParams,
  753.                 this.openspcoopProperties.getAttachmentsProcessingMode());
  754.         try {
  755.             OpenSPCoop2Message msg = pr.getMessage_throwParseException();
  756.             msg.readResourcesFrom(smc.msgContext);
  757.             return msg;
  758.         }catch(Exception e) {
  759.             throw new MessageException(e.getMessage(),e);
  760.         }
  761.     }

  762.     private void fillTransactionContext(Context context, InputStream is) throws UtilsException {
  763.         SerializedContext serializedContext = null;
  764.         try {
  765.             org.openspcoop2.message.context.utils.serializer.JaxbDeserializer deserializer =
  766.                     new org.openspcoop2.message.context.utils.serializer.JaxbDeserializer();
  767.             serializedContext = deserializer.readSerializedContext(is);
  768.            
  769.             if(serializedContext!=null && serializedContext.sizePropertyList()>0) {
  770.                 JavaDeserializer jDeserializer = new JavaDeserializer();
  771.                 for (SerializedParameter p : serializedContext.getPropertyList()) {
  772.                     Object o = jDeserializer.readObject(new ByteArrayInputStream(p.getBase()), Class.forName(p.getClasse()));
  773.                     context.addObject(org.openspcoop2.utils.Map.newMapKey(p.getNome()), o);
  774.                 }
  775.             }
  776.            
  777.         }catch(Exception e) {
  778.             throw new UtilsException(e.getMessage(),e);
  779.         }  
  780.     }








  781.     /* ********  D E L E T E  ******** */

  782.     /**
  783.      * Elimina un messaggio completamente, sia dal filesystem che dal db
  784.      *
  785.      *
  786.      */
  787.     public void delete(boolean isRichiesta,boolean onewayVersione11, java.sql.Timestamp data) throws UtilsException{
  788.         if((this.openspcoopstate instanceof OpenSPCoopStateful) || onewayVersione11) {
  789.             StateMessage stateMSG = (isRichiesta) ?  (StateMessage)this.openspcoopstate.getStatoRichiesta()
  790.                     : (StateMessage)this.openspcoopstate.getStatoRisposta();
  791.             Connection connectionDB = stateMSG.getConnectionDB();

  792.             deleteStateful(connectionDB, data);
  793.            
  794.         }else if (this.openspcoopstate instanceof OpenSPCoopStateless){
  795.             // NOP
  796.         }else{
  797.             throw new UtilsException("Metodo invocato con IState non valido");
  798.         }
  799.     }
  800.    
  801.     private void deleteStateful(Connection connectionDB, java.sql.Timestamp data) throws UtilsException {
  802.         PreparedStatement pstmt = null;
  803.         try{
  804.             // Eliminazione da FileSystem
  805.             if(this.saveOnFS){
  806.                 deleteFileSystem();
  807.             }

  808.             //  Eliminazione from DB.
  809.             String sql = buildDeleteStatement(data);
  810.             pstmt= connectionDB.prepareStatement(sql);
  811.             pstmt.setString(1,this.idMessaggio);
  812.             if(Costanti.INBOX.equals(this.box))
  813.                 pstmt.setString(2,Costanti.INBOX);
  814.             else
  815.                 pstmt.setString(2,Costanti.OUTBOX);
  816.             if(data!=null) {
  817.                 pstmt.setTimestamp(3, data);
  818.             }
  819.             pstmt.execute();
  820.             pstmt.close();

  821.         }catch(Exception e){
  822.             try{
  823.                 if( pstmt != null )
  824.                     pstmt.close();
  825.             } catch(Exception er) {
  826.                 // close
  827.             }
  828.             String errorMsg = "SOAP_MESSAGE, delete: "+this.box+"/"+this.idMessaggio+": "+e.getMessage();      
  829.             logError(errorMsg,e);
  830.             throw new UtilsException(errorMsg,e);
  831.         }
  832.     }
  833.    
  834.     private String buildDeleteStatement(java.sql.Timestamp data) {
  835.         StringBuilder query = new StringBuilder();
  836.         query.append("DELETE from ");
  837.         query.append(GestoreMessaggi.DEFINIZIONE_MESSAGGI);
  838.         query.append(" WHERE ");
  839.         query.append(GestoreMessaggi.DEFINIZIONE_MESSAGGI_COLUMN_ID_MESSAGGIO);
  840.         query.append(" = ? AND ");
  841.         query.append(GestoreMessaggi.DEFINIZIONE_MESSAGGI_COLUMN_TIPO_MESSAGGIO);
  842.         query.append(" = ?");      
  843.         if(data!=null) {
  844.             query.append(" AND ");
  845.             query.append(GestoreMessaggi.DEFINIZIONE_MESSAGGI_COLUMN_ORA_REGISTRAZIONE);
  846.             query.append("<=?");
  847.         }
  848.         return query.toString();
  849.     }
  850.    
  851.     /**
  852.      * Elimina un messaggio completamente filesystem
  853.      *
  854.      *
  855.      */
  856.     public void deleteMessageFromFileSystem() {


  857.         try{
  858.             // Eliminazione da FileSystem
  859.             if(this.saveOnFS){
  860.                
  861.                 deleteFileSystem();
  862.                
  863.             }

  864.         }catch(Exception e){
  865.             String errorMsg = "SOAP_MESSAGE, deleteMessageFromFileSystem: "+this.box+"/"+this.idMessaggio+": "+e.getMessage();      
  866.             this.getLog().error(errorMsg,e);
  867.         }
  868.     }
  869.    
  870.     private void deleteFileSystem() throws UtilsException {
  871.        
  872.         String saveDir = getBaseDir();
  873.         checkInizializzazioneWorkingDir(saveDir);
  874.        
  875.         String pathBytes = saveDir + this.keyMsgBytes;
  876.         File fileDeleteBytes = new File(pathBytes);
  877.         if(fileDeleteBytes.exists()){
  878.             deleteFileIgnoreException(fileDeleteBytes);
  879.         }  
  880.                        
  881.         String pathContext = saveDir + this.keyMsgContext;
  882.         File fileDeleteContext = new File(pathContext);
  883.         if(fileDeleteContext.exists()){
  884.             deleteFileIgnoreException(fileDeleteContext);
  885.         }
  886.        
  887.         String pathResponseBytes = saveDir + this.keyMsgResponseBytes;
  888.         File fileDeleteResponseBytes = new File(pathResponseBytes);
  889.         if(fileDeleteResponseBytes.exists()){
  890.             deleteFileIgnoreException(fileDeleteResponseBytes);
  891.         }
  892.        
  893.         String pathResponseContext = saveDir + this.keyMsgResponseContext;
  894.         File fileDeleteResponseContext = new File(pathResponseContext);
  895.         if(fileDeleteResponseContext.exists()){
  896.             deleteFileIgnoreException(fileDeleteResponseContext);
  897.         }
  898.        
  899.         String pathTransactionContext = saveDir + this.keyMsgTransactionContext;
  900.         File fileDeleteTransactionContext = new File(pathTransactionContext);
  901.         if(fileDeleteTransactionContext.exists()){
  902.             deleteFileIgnoreException(fileDeleteTransactionContext);
  903.         }
  904.        
  905.     }

  906.    
  907.     private void deleteFileIgnoreException(File file) {
  908.         try {
  909.             Files.delete(file.toPath());
  910.         }catch(Exception e) {
  911.             // ignore
  912.         }
  913.     }
  914. }

  915. class SavedMessageContext {
  916.    
  917.     MessageContext msgContext;
  918.     MessageType mt;
  919.     MessageRole mr;
  920.     String contentTypeNormalized;
  921.    
  922. }