QueueManager.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.config;

  21. import java.util.Map;
  22. import java.util.concurrent.ConcurrentHashMap;

  23. import javax.jms.Connection;
  24. import javax.jms.ConnectionFactory;
  25. import javax.jms.JMSException;
  26. import javax.jms.Queue;
  27. import javax.jms.Session;

  28. import org.openspcoop2.core.commons.CoreException;
  29. import org.openspcoop2.core.commons.IMonitoraggioRisorsa;
  30. import org.openspcoop2.core.id.IDSoggetto;
  31. import org.openspcoop2.pdd.logger.MsgDiagnostico;
  32. import org.openspcoop2.pdd.mdb.ConsegnaContenutiApplicativi;
  33. import org.openspcoop2.pdd.mdb.Imbustamento;
  34. import org.openspcoop2.pdd.mdb.ImbustamentoRisposte;
  35. import org.openspcoop2.pdd.mdb.InoltroBuste;
  36. import org.openspcoop2.pdd.mdb.InoltroRisposte;
  37. import org.openspcoop2.pdd.mdb.Sbustamento;
  38. import org.openspcoop2.pdd.mdb.SbustamentoRisposte;
  39. import org.openspcoop2.pdd.services.core.RicezioneBuste;
  40. import org.openspcoop2.pdd.services.core.RicezioneContenutiApplicativi;
  41. import org.openspcoop2.utils.UtilsException;
  42. import org.openspcoop2.utils.date.DateManager;
  43. import org.openspcoop2.utils.resources.GestoreJNDI;


  44. /**
  45.  * Contiene la gestione delle connessioni al broker delle code JMS.
  46.  * Il nome della risorsa JNDI da cui e' possibili attingere connessioni verso il Provider JMS,
  47.  * viene selezionato attraverso le impostazioni lette dal file 'govway.properties'
  48.  * e gestite attraverso l'utilizzo della classe  {@link org.openspcoop2.pdd.config.OpenSPCoop2Properties}.
  49.  *
  50.  *
  51.  * @author Poli Andrea (apoli@link.it)
  52.  * @author $Author$
  53.  * @version $Rev$, $Date$
  54.  */

  55. public class QueueManager implements IMonitoraggioRisorsa{

  56.     private static final String ID_MODULO = "QueueManager";

  57.     /** Coda su cui il webService 'RicezioneContenutiApplicativi_XXX' sta' attendendo una risposta */
  58.     private static Queue queueRicezioneContenutiApplicativi;
  59.     /** Coda su cui il webService 'RicezioneBuste_XXX' sta' attendendo una risposta */
  60.     private static Queue queueRicezioneBuste;
  61.     /** Coda su cui l'MDB 'Imbustamento' sta' attendendo un messaggio */
  62.     private static Queue queueImbustamento;
  63.     /** Coda su cui l'MDB 'ImbustamentoRisposte' sta' attendendo un messaggio */
  64.     private static Queue queueImbustamentoRisposte;
  65.     /** Coda su cui l'MDB 'Sbustamento' sta' attendendo un messaggio */
  66.     private static Queue queueSbustamento;
  67.     /** Coda su cui l'MDB 'SbustamentoRisposte' sta' attendendo un messaggio */
  68.     private static Queue queueSbustamentoRisposte;
  69.     /** Coda su cui l'MDB 'InoltroBuste' sta' attendendo un messaggio */
  70.     private static Queue queueInoltroBuste;
  71.     /** Coda su cui l'MDB 'InoltroRisposte' sta' attendendo un messaggio */
  72.     private static Queue queueInoltroRisposte;
  73.     /** Coda su cui l'MDB 'ConsegnaMessaggi' sta' attendendo un messaggio */
  74.     private static Queue queueConsegnaContenutiApplicativi;

  75.    
  76.     /** OpenSPCoopProperties */
  77.     private static OpenSPCoop2Properties openspcoopProperties = OpenSPCoop2Properties.getInstance();
  78.    
  79.     /** Informazione sui proprietari che hanno richiesto una connessione */
  80.     protected static Map<String,Resource> risorseInGestione = new ConcurrentHashMap<>();
  81.    
  82.     public static String[] getStatoRisorse() {
  83.        
  84.         String[] sNull = null;
  85.         Object[] o = QueueManager.risorseInGestione.values().toArray(new Resource[0]);
  86.         if(! (o instanceof Resource[]))
  87.             return sNull;
  88.         Resource[] resources = (Resource[]) o;
  89.         if(resources.length<=0)
  90.             return sNull;
  91.    
  92.         String [] r = new String[resources.length];
  93.         for(int i=0; i<resources.length; i++){
  94.             Resource rr = resources[i];
  95.             r[i] = rr.getIdentificativoPorta()+"."+rr.getModuloFunzionale();
  96.             if(rr.getIdTransazione()!=null){
  97.                 r[i] = r[i] +"."+rr.getIdTransazione();
  98.             }
  99.             r[i] = r[i] +" ("+rr.getDate().toString()+")";
  100.         }
  101.         return r;
  102.     }


  103.     /** QueueManager */
  104.     private static QueueManager manager = null;

  105.     /**
  106.      * Il Metodo si occupa di inizializzare il QueueManager
  107.      *
  108.      * @param jndiName Nome JNDI del QueueConnectionFactory
  109.      * @param contextFactory Contesto JNDI da utilizzare per la connection factory/openSPCoopQueueManager
  110.      * @throws OpenSPCoop2ConfigurationException
  111.      *
  112.      */
  113.     public static void initialize(String jndiName,
  114.             java.util.Properties contextFactory) throws OpenSPCoop2ConfigurationException {

  115.         // Provo ad ottenere un QueueManager
  116.         QueueManager.manager = new QueueManager(jndiName,contextFactory);

  117.     }
  118.    
  119.     /**
  120.      * Il Metodo si occupa di inizializzare le code di ricezione
  121.      *
  122.      * @param contextQueue Contesto JNDI da utilizzare per le code interne
  123.      * @throws UtilsException
  124.      *
  125.      */
  126.     public static void initializeQueueNodeReceiver(java.util.Properties contextQueue) throws UtilsException {

  127.         // Tabella per i nomi jndi delle code
  128.         java.util.Map<String,String> nomiJndi =
  129.             OpenSPCoop2Properties.getInstance().getJNDIQueueName(true,false);
  130.            
  131.         // Inizializzazione Code
  132.         GestoreJNDI jndiQueue = new GestoreJNDI(contextQueue);
  133.         QueueManager.queueRicezioneContenutiApplicativi =
  134.             (Queue) jndiQueue.lookup(nomiJndi.get(RicezioneContenutiApplicativi.ID_MODULO));
  135.         QueueManager.queueRicezioneBuste=
  136.             (Queue) jndiQueue.lookup(nomiJndi.get(RicezioneBuste.ID_MODULO));

  137.     }


  138.     /**
  139.      * Il Metodo si occupa di inizializzare le code di spedizione
  140.      *
  141.      * @param contextQueue Contesto JNDI da utilizzare per le code interne
  142.      * @throws UtilsException
  143.      *
  144.      */
  145.     public static void initializeQueueNodeSender(java.util.Properties contextQueue) throws UtilsException {

  146.         // Tabella per i nomi jndi delle code
  147.         java.util.Map<String,String> nomiJndi = OpenSPCoop2Properties.getInstance().getJNDIQueueName(false,true);
  148.        
  149.         // Inizializzazione Code
  150.         GestoreJNDI jndiQueue = new GestoreJNDI(contextQueue);
  151.         QueueManager.queueImbustamento=
  152.             (Queue) jndiQueue.lookup(nomiJndi.get(Imbustamento.ID_MODULO));
  153.         QueueManager.queueImbustamentoRisposte=
  154.             (Queue) jndiQueue.lookup(nomiJndi.get(ImbustamentoRisposte.ID_MODULO));
  155.         QueueManager.queueSbustamento=
  156.             (Queue) jndiQueue.lookup(nomiJndi.get(Sbustamento.ID_MODULO));
  157.         QueueManager.queueSbustamentoRisposte=
  158.             (Queue) jndiQueue.lookup(nomiJndi.get(SbustamentoRisposte.ID_MODULO));
  159.         QueueManager.queueInoltroBuste=
  160.             (Queue) jndiQueue.lookup(nomiJndi.get(InoltroBuste.ID_MODULO));
  161.         QueueManager.queueInoltroRisposte=
  162.             (Queue) jndiQueue.lookup(nomiJndi.get(InoltroRisposte.ID_MODULO));
  163.         QueueManager.queueConsegnaContenutiApplicativi=
  164.             (Queue) jndiQueue.lookup(nomiJndi.get(ConsegnaContenutiApplicativi.ID_MODULO));
  165.     }
  166.    
  167.    
  168.    
  169.    
  170.     /**
  171.      * Ritorna l'istanza di questo QueueManager
  172.      *
  173.      * @return Istanza di QueueManager
  174.      *
  175.      */
  176.     public static QueueManager getInstance(){
  177.         if(QueueManager.manager==null) {
  178.             // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED': l'istanza viene creata allo startup
  179.             synchronized (QueueManager.class) {
  180.                 return QueueManager.manager;
  181.             }
  182.         }
  183.         return QueueManager.manager;
  184.     }

  185.    
  186.     /**
  187.      * Restituisce la coda associata al nodo con identificativo <var>nomeNodo</var>.
  188.      *
  189.      * @param idNodo Identificatore del nodo.
  190.      *
  191.      */
  192.     public Queue getQueue(String idNodo) {
  193.         if(idNodo.startsWith(RicezioneContenutiApplicativi.ID_MODULO))
  194.             return QueueManager.queueRicezioneContenutiApplicativi;
  195.         else if(idNodo.startsWith(RicezioneBuste.ID_MODULO))
  196.             return QueueManager.queueRicezioneBuste;
  197.         else if(Imbustamento.ID_MODULO.equals(idNodo))
  198.             return QueueManager.queueImbustamento;
  199.         else if(ImbustamentoRisposte.ID_MODULO.equals(idNodo))
  200.             return QueueManager.queueImbustamentoRisposte;
  201.         else if(Sbustamento.ID_MODULO.equals(idNodo))
  202.             return QueueManager.queueSbustamento;
  203.         else if(SbustamentoRisposte.ID_MODULO.equals(idNodo))
  204.             return QueueManager.queueSbustamentoRisposte;
  205.         else if(InoltroBuste.ID_MODULO.equals(idNodo))
  206.             return QueueManager.queueInoltroBuste;
  207.         else if(InoltroRisposte.ID_MODULO.equals(idNodo))
  208.             return QueueManager.queueInoltroRisposte;
  209.         else if(ConsegnaContenutiApplicativi.ID_MODULO.equals(idNodo))
  210.             return QueueManager.queueConsegnaContenutiApplicativi;
  211.         else
  212.             return null;
  213.     }
  214.    
  215.    
  216.    
  217.    
  218.    
  219.     /** ConnectionFactory dove attingere connessioni */
  220.     private ConnectionFactory qcf = null;
  221.     /** MsgDiagnostico */
  222.     private MsgDiagnostico msgDiag = null;
  223.    
  224.     /**
  225.      * Costruttore
  226.      *
  227.      * @param jndiName Nome JNDI del QueueConnectionFactory
  228.      * @param context Contesto JNDI da utilizzare
  229.      *
  230.      */
  231.     private QueueManager(String jndiName,java.util.Properties context) throws OpenSPCoop2ConfigurationException{

  232.         this.msgDiag = MsgDiagnostico.newInstance("WrapperQueueManager");
  233.         try {
  234.             GestoreJNDI jndi = new GestoreJNDI(context);

  235.             // ConnectionFactory
  236.             this.qcf = (ConnectionFactory) jndi.lookup(jndiName);
  237.         }
  238.         catch(Exception e) {
  239.             throw new OpenSPCoop2ConfigurationException("WrapperQueueManager: "+e.getMessage(),e);
  240.         }

  241.     }





  242.     /**
  243.      * Ritorna un JMSObject che contiene una connessione/sessione al JMS Broker
  244.      *
  245.      * @param idPDD Identificatore della porta di dominio.
  246.      * @param modulo Modulo che richiede una connessione.
  247.      * @return JMSObject.
  248.      *
  249.      */
  250.     public Resource getResource(IDSoggetto idPDD,String modulo,String idTransazione) throws OpenSPCoop2ConfigurationException{
  251.        
  252.         Resource risorsa = new Resource();
  253.         try {
  254.             Connection con = this.qcf.createConnection();
  255.             checkConnection(con);

  256.             // Sessione
  257.             Session s = con.createSession(false,QueueManager.openspcoopProperties.getAcknowledgeModeSessioneConnectionFactory());
  258.             if(s == null){
  259.                 con.close();
  260.                 throw new OpenSPCoop2ConfigurationException("SessioneNonDisponibile");
  261.             }

  262.             // Object JMS
  263.            
  264.             JMSObject jms = new JMSObject();
  265.             jms.setConnection(con);
  266.             jms.setSession(s);
  267.            
  268.             String idUnivoco = Resource.generaIdentificatoreUnivoco(idPDD, modulo);
  269.             risorsa.setId(idUnivoco);
  270.             risorsa.setDate(DateManager.getDate());
  271.             risorsa.setIdentificativoPorta(idPDD);
  272.             risorsa.setModuloFunzionale(modulo);
  273.             risorsa.setResource(jms);
  274.             risorsa.setResourceType(JMSObject.class.getName());
  275.             risorsa.setIdTransazione(idTransazione);
  276.                
  277.             QueueManager.risorseInGestione.put(idUnivoco, risorsa);
  278.            
  279.             return risorsa;

  280.         }
  281.         catch(Exception e) {
  282.             this.msgDiag.aggiornaFiltri();
  283.             this.msgDiag.setDominio(idPDD);
  284.             this.msgDiag.setFunzione("QueueManager."+modulo);
  285.             this.msgDiag.logFatalError(e, "Richiesta connessione al QueueManager");
  286.             throw new OpenSPCoop2ConfigurationException("getJMSObject: "+e.getMessage());
  287.         }
  288.     }
  289.     private static void checkConnection(Connection con) throws OpenSPCoop2ConfigurationException {
  290.         if(con == null)
  291.             throw new OpenSPCoop2ConfigurationException("ConnessioneNonDisponibile");
  292.     }
  293.     /**
  294.      * Restituisce un JMSObject al pool
  295.      *
  296.      * @param idPDD Identificatore della porta di dominio.
  297.      * @param modulo Modulo che richiede una connessione.
  298.      * @param resource JMSObject.
  299.      *
  300.      */
  301.     public void releaseResource(IDSoggetto idPDD,String modulo,Resource resource) throws OpenSPCoop2ConfigurationException{
  302.         try {
  303.             if(resource!=null){
  304.                 if(resource.getResource()!=null){
  305.                     JMSObject jms = (JMSObject) resource.getResource();
  306.                     // Controllo dell'oggetto ricevuto
  307.                     if(jms == null){
  308.                         throw new OpenSPCoop2ConfigurationException("PassivateObject[JMSObjectNull]");
  309.                     }
  310.                     if(jms.getConnection()==null){
  311.                         throw new OpenSPCoop2ConfigurationException("PassivateObject[ConnectionNull]");
  312.                     }
  313.                     if(jms.getSession()==null){
  314.                         throw new OpenSPCoop2ConfigurationException("PassivateObject[SessionNull]");
  315.                     }

  316.                     // rilascio
  317.                     close(jms);
  318.                    
  319.                 }
  320.                 if(QueueManager.risorseInGestione.containsKey(resource.getId()))
  321.                     QueueManager.risorseInGestione.remove(resource.getId());
  322.             }
  323.         }
  324.         catch(Exception e) {
  325.             this.msgDiag.aggiornaFiltri();
  326.             this.msgDiag.setDominio(idPDD);
  327.             this.msgDiag.setFunzione("QueueManager."+modulo);
  328.             this.msgDiag.logFatalError(e, "Rilasciata connessione al QueueManager");
  329.             throw new OpenSPCoop2ConfigurationException("releaseJMSObject: "+e.getMessage());
  330.         }
  331.     }
  332.     private void close(JMSObject jms) throws JMSException {
  333.         try{
  334.             jms.getSession().close();
  335.         }catch(Exception e){
  336.             jms.getConnection().close();
  337.             throw e;
  338.         }
  339.         jms.getConnection().close();
  340.     }
  341.    
  342.    




  343.     /**
  344.      * Metodo che verica la connessione ad una risorsa.
  345.      * Se la connessione non e' presente, viene lanciata una eccezione che contiene il motivo della mancata connessione
  346.      *
  347.      * @throws DriverException eccezione che contiene il motivo della mancata connessione
  348.      */
  349.     @Override
  350.     public void isAlive() throws CoreException{
  351.         Resource resource = null;
  352.         IDSoggetto idSoggettAlive = new IDSoggetto();
  353.         idSoggettAlive.setCodicePorta(ID_MODULO);
  354.         idSoggettAlive.setTipo(ID_MODULO);
  355.         idSoggettAlive.setNome(ID_MODULO);
  356.         try{
  357.             resource = this.getResource(idSoggettAlive, "CheckIsAlive", null);
  358.             if(resource == null)
  359.                 throw new CoreException("Resource is null");
  360.             if(resource.getResource() == null)
  361.                 throw new CoreException("JMSObject is null");
  362.             JMSObject jmsObject = (JMSObject) resource.getResource();
  363.             if(jmsObject.getConnection()==null)
  364.                 throw new CoreException("Connessione is null");
  365.             if(jmsObject.getSession()==null)
  366.                 throw new CoreException("Sessione is null");
  367.             Connection connectionJMS = jmsObject.getConnection();
  368.             // test
  369.             connectionJMS.getClientID();
  370.         }catch(Exception e){
  371.             throw new CoreException("Connessione al broker JMS non disponibile: "+e.getMessage(),e);
  372.         }finally{
  373.             try{
  374.                 this.releaseResource(idSoggettAlive, "CheckIsAlive" ,resource);
  375.             }catch(Exception e){
  376.                 // close
  377.             }
  378.         }
  379.     }
  380. }