ConnettoreHTTP.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.connettori;

  21. import java.io.FileInputStream;
  22. import java.io.OutputStream;
  23. import java.net.Authenticator;
  24. import java.net.HttpURLConnection;
  25. import java.net.InetSocketAddress;
  26. import java.net.PasswordAuthentication;
  27. import java.net.Proxy;
  28. import java.net.URL;
  29. import java.net.URLConnection;
  30. import java.util.ArrayList;
  31. import java.util.HashMap;
  32. import java.util.Iterator;
  33. import java.util.List;
  34. import java.util.Map;

  35. import javax.net.ssl.HostnameVerifier;
  36. import javax.net.ssl.HttpsURLConnection;
  37. import javax.net.ssl.SSLSocketFactory;

  38. import org.apache.commons.lang.StringUtils;
  39. import org.openspcoop2.core.config.ResponseCachingConfigurazione;
  40. import org.openspcoop2.core.config.constants.CostantiConfigurazione;
  41. import org.openspcoop2.core.constants.CostantiConnettori;
  42. import org.openspcoop2.core.constants.TipiConnettore;
  43. import org.openspcoop2.core.constants.TransferLengthModes;
  44. import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
  45. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  46. import org.openspcoop2.message.constants.Costanti;
  47. import org.openspcoop2.message.constants.MessageType;
  48. import org.openspcoop2.message.soap.TunnelSoapUtils;
  49. import org.openspcoop2.pdd.mdb.ConsegnaContenutiApplicativi;
  50. import org.openspcoop2.utils.NameValue;
  51. import org.openspcoop2.utils.Utilities;
  52. import org.openspcoop2.utils.UtilsException;
  53. import org.openspcoop2.utils.date.DateManager;
  54. import org.openspcoop2.utils.io.Base64Utilities;
  55. import org.openspcoop2.utils.io.DumpByteArrayOutputStream;
  56. import org.openspcoop2.utils.transport.TransportUtils;
  57. import org.openspcoop2.utils.transport.http.HttpBodyParameters;
  58. import org.openspcoop2.utils.transport.http.HttpConstants;
  59. import org.openspcoop2.utils.transport.http.HttpUtilities;
  60. import org.openspcoop2.utils.transport.http.RFC2047Utilities;
  61. import org.openspcoop2.utils.transport.http.SSLUtilities;
  62. import org.openspcoop2.utils.transport.http.WrappedLogSSLSocketFactory;



  63. /**
  64.  * Classe utilizzata per effettuare consegne di messaggi Soap, attraverso
  65.  * l'invocazione di un server http.
  66.  *
  67.  *
  68.  * @author Poli Andrea (apoli@link.it)
  69.  * @author $Author$
  70.  * @version $Rev$, $Date$
  71.  */

  72. public class ConnettoreHTTP extends ConnettoreBaseHTTP {

  73.     // NOTA: HttpMethod PATCH/LINK/UNLINK funziona solo con java 8
  74.     // Con java7 si ottiene l'errore:
  75.     // Caused by: java.net.ProtocolException: HTTP method PATCH doesn't support output
  76.     //    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1081)


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

  79.     /** Proxy Configuration */
  80.     protected Proxy.Type proxyType = null;
  81.     protected String proxyHostname = null;
  82.     protected int proxyPort;
  83.     protected String proxyUsername;
  84.     protected String proxyPassword;
  85.    
  86.     /** Redirect */
  87.     protected boolean followRedirects = false;
  88.     protected String routeRedirect = null;
  89.     protected int numberRedirect = 0;
  90.     protected int maxNumberRedirects = 5;
  91.     protected String redirectLocation = null;
  92.     protected String originalAbsolutePrefixForRelativeRedirectLocation = null;
  93.    
  94.     /** TransferMode */
  95.     protected TransferLengthModes tlm = null;
  96.     protected int chunkLength = -1;
  97.    
  98.     /** Connessione */
  99.     protected HttpURLConnection httpConn = null;
  100.    
  101.     /** KeepAlive */
  102.     protected boolean keepAlive = false;
  103.            
  104.     /* Costruttori */
  105.     public ConnettoreHTTP(){
  106.         this.connettoreHttps = false;
  107.     }
  108.     public ConnettoreHTTP(boolean https){
  109.         this.connettoreHttps = https;
  110.     }
  111.    
  112.    
  113.    
  114.     /* ********  METODI  ******** */
  115.    
  116.     @Override
  117.     protected boolean initializePreSend(ResponseCachingConfigurazione responseCachingConfig, ConnettoreMsg request) {
  118.         return this.initialize(request, true, responseCachingConfig);
  119.     }
  120.    
  121.     @Override
  122.     protected boolean send(ConnettoreMsg request) {

  123.         // HTTPS
  124.         try{
  125.             this.setSSLContext();
  126.         }catch(Exception e){
  127.             this.eccezioneProcessamento = e;
  128.             this.logger.error("[HTTPS error]"+ this.readExceptionMessageFromException(e),e);
  129.             this.errore = "[HTTPS error]"+ this.readExceptionMessageFromException(e);
  130.             return false;
  131.         }
  132.    
  133.         // Proxy
  134.         if(this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE)!=null){
  135.            
  136.             String tipo = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE).trim();
  137.             if(CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE_VALUE_HTTP.equals(tipo)){
  138.                 this.proxyType = Proxy.Type.HTTP;
  139.             }
  140.             else if(CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE_VALUE_HTTPS.equals(tipo)){
  141.                 this.proxyType = Proxy.Type.HTTP;
  142.             }
  143.             else{
  144.                 this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE
  145.                         +"' non corretta. Impostato un tipo sconosciuto ["+tipo+"] (valori ammessi: "+CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE_VALUE_HTTP
  146.                         +","+CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE_VALUE_HTTPS+")";
  147.                 return false;
  148.             }
  149.            
  150.             this.proxyHostname = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_HOSTNAME);
  151.             if(this.proxyHostname!=null){
  152.                 this.proxyHostname = this.proxyHostname.trim();
  153.             }else{
  154.                 this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_HOSTNAME+
  155.                         "' non impostata, obbligatoria in presenza della proprietà '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE+"'";
  156.                 return false;
  157.             }
  158.            
  159.             String proxyPortTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_PORT);
  160.             if(proxyPortTmp!=null){
  161.                 proxyPortTmp = proxyPortTmp.trim();
  162.             }else{
  163.                 this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_PORT+
  164.                         "' non impostata, obbligatoria in presenza della proprietà '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_TYPE+"'";
  165.                 return false;
  166.             }
  167.             try{
  168.                 this.proxyPort = Integer.parseInt(proxyPortTmp);
  169.             }catch(Exception e){
  170.                 this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_PORT+"' non corretta: "+this.readExceptionMessageFromException(e);
  171.                 return false;
  172.             }
  173.            
  174.            
  175.             this.proxyUsername = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_USERNAME);
  176.             if(this.proxyUsername!=null){
  177.                 this.proxyUsername = this.proxyUsername.trim();
  178.             }
  179.            
  180.             this.proxyPassword = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_PROXY_PASSWORD);
  181.             if(this.proxyPassword!=null){
  182.                 this.proxyPassword = this.proxyPassword.trim();
  183.             }else{
  184.                 if(this.proxyUsername!=null){
  185.                     this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_PASSWORD
  186.                             +"' non impostata, obbligatoria in presenza della proprietà '"+CostantiConnettori.CONNETTORE_HTTP_PROXY_USERNAME+"'";
  187.                     return false;
  188.                 }
  189.             }
  190.         }
  191.                
  192.         // TransferMode
  193.         if(ConsegnaContenutiApplicativi.ID_MODULO.equals(this.idModulo)){
  194.             this.tlm = this.openspcoopProperties.getTransferLengthModes_consegnaContenutiApplicativi();
  195.             this.chunkLength = this.openspcoopProperties.getChunkLength_consegnaContenutiApplicativi();
  196.         }
  197.         else{
  198.             // InoltroBuste e InoltroRisposte
  199.             this.tlm = this.openspcoopProperties.getTransferLengthModes_inoltroBuste();
  200.             this.chunkLength = this.openspcoopProperties.getChunkLength_inoltroBuste();
  201.         }
  202.         String tlmTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_DATA_TRANSFER_MODE);
  203.         if(tlmTmp!=null){
  204.             tlmTmp = tlmTmp.trim();
  205.             try{
  206.                 this.tlm = TransferLengthModes.getTransferLengthModes(tlmTmp);
  207.             }catch(Exception e){
  208.                 this.errore = "Proprieta' '"+CostantiConnettori.CONNETTORE_HTTP_DATA_TRANSFER_MODE
  209.                         +"' non impostata correttamente: "+e.getMessage();
  210.                 return false;
  211.             }
  212.         }
  213.         if(TransferLengthModes.TRANSFER_ENCODING_CHUNKED.equals(this.tlm)){
  214.             tlmTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_DATA_TRANSFER_MODE_CHUNK_SIZE);
  215.             //this.log.info("PROPERTY! ("+redirectTmp+")");
  216.             if(tlmTmp!=null){
  217.                 tlmTmp = tlmTmp.trim();
  218.                 this.chunkLength = Integer.parseInt(tlmTmp);
  219.             }
  220.         }
  221.        
  222.         // Redirect
  223.         if(ConsegnaContenutiApplicativi.ID_MODULO.equals(this.idModulo)){
  224.             if(this.isSoap) {
  225.                 this.followRedirects = this.openspcoopProperties.isFollowRedirects_consegnaContenutiApplicativi_soap();
  226.             }else {
  227.                 this.followRedirects = this.openspcoopProperties.isFollowRedirects_consegnaContenutiApplicativi_rest();
  228.             }
  229.             this.maxNumberRedirects = this.openspcoopProperties.getFollowRedirectsMaxHop_consegnaContenutiApplicativi();
  230.         }
  231.         else{
  232.             // InoltroBuste e InoltroRisposte
  233.             if(this.isSoap) {
  234.                 this.followRedirects = this.openspcoopProperties.isFollowRedirects_inoltroBuste_soap();
  235.             }
  236.             else {
  237.                 this.followRedirects = this.openspcoopProperties.isFollowRedirects_inoltroBuste_rest();
  238.             }
  239.             this.maxNumberRedirects = this.openspcoopProperties.getFollowRedirectsMaxHop_inoltroBuste();
  240.         }

  241.         String redirectTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_FOLLOW);
  242.         if(redirectTmp!=null){
  243.             redirectTmp = redirectTmp.trim();
  244.             this.followRedirects = "true".equalsIgnoreCase(redirectTmp) || CostantiConfigurazione.ABILITATO.getValue().equalsIgnoreCase(redirectTmp);
  245.         }
  246.         //this.log.info("FOLLOW! ("+this.followRedirects+")");
  247.         if(this.followRedirects){
  248.            
  249.             redirectTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_MAX_HOP);
  250.             //this.log.info("PROPERTY! ("+redirectTmp+")");
  251.             if(redirectTmp!=null){
  252.                 redirectTmp = redirectTmp.trim();
  253.                 this.maxNumberRedirects = Integer.parseInt(redirectTmp);
  254.             }
  255.            
  256.             redirectTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_NUMBER);
  257.             //this.log.info("PROPERTY! ("+redirectTmp+")");
  258.             if(redirectTmp!=null){
  259.                 redirectTmp = redirectTmp.trim();
  260.                 this.numberRedirect = Integer.parseInt(redirectTmp);
  261.             }
  262.            
  263.             redirectTmp = this.properties.get(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_ROUTE);
  264.             //this.log.info("PROPERTY! ("+redirectTmp+")");
  265.             if(redirectTmp!=null){
  266.                 redirectTmp = redirectTmp.trim();
  267.                 this.routeRedirect = redirectTmp;
  268.             }
  269.         }
  270.            
  271.         return sendHTTP(request);

  272.     }

  273.     /**
  274.      * Si occupa di effettuare la consegna HTTP_POST (sbustando il messaggio SOAP).
  275.      * Si aspetta di ricevere una risposta non sbustata.
  276.      *
  277.      * @return true in caso di consegna con successo, false altrimenti
  278.      *
  279.      */
  280.    
  281.     protected boolean sendHTTP(ConnettoreMsg request){
  282.        
  283.         int connectionTimeout = -1;
  284.         boolean connectionTimeoutConfigurazioneGlobale = true;
  285.         int readConnectionTimeout = -1;
  286.         boolean readConnectionTimeoutConfigurazioneGlobale = true;
  287.         try{

  288.             // Creazione URL
  289.             if(this.debug)
  290.                 this.logger.debug("Creazione URL...");
  291.             this.buildLocation();      
  292.             if(this.debug)
  293.                 this.logger.debug("Creazione URL ["+this.location+"]...");
  294.             URL url = new URL( this.location );

  295.            
  296.             // Collezione header di trasporto per dump
  297.             Map<String, List<String>> propertiesTrasportoDebug = null;
  298.             if(this.isDumpBinarioRichiesta()) {
  299.                 propertiesTrasportoDebug = new HashMap<>();
  300.             }

  301.            
  302.             // Creazione Connessione
  303.             URLConnection connection = null;
  304.             if(this.proxyType==null){
  305.                 if(this.debug)
  306.                     this.logger.info("Creazione connessione alla URL ["+this.location+"]...",false);
  307.                 connection = url.openConnection();
  308.             }
  309.             else{
  310.                 if(this.debug)
  311.                     this.logger.info("Creazione connessione alla URL ["+this.location+"] (via proxy "+
  312.                                 this.proxyHostname+":"+this.proxyPort+") (username["+this.proxyUsername+"] password["+this.proxyPassword+"])...",false);
  313.                    
  314.                 if(this.proxyUsername!=null){
  315.                     //The problem with the 2nd code is that it sets a new default Authenticator and
  316.                     // I don't want to do that, because this proxy is only used by a part of the application
  317.                     // and a different part of the application could be using a different proxy.
  318.                     // Vedi articolo: http://stackoverflow.com/questions/34877470/basic-proxy-authentification-for-https-urls-returns-http-1-0-407-proxy-authentic
  319.                     // Authenticator.setDefault(new HttpAuthenticator(this.proxyUsername, this.proxyPassword));
  320.                    
  321.                     // Soluzione attuale:
  322.                     // Dopo aver instaurato la connesione, più sotto nel codice, viene creato l'header Proxy-Authorization
  323.                     // NOTA: Works for HTTP only! Doesn't work for HTTPS!
  324.                 }
  325.                
  326.                 Proxy proxy = new Proxy(this.proxyType, new InetSocketAddress(this.proxyHostname, this.proxyPort));
  327.                 connection = url.openConnection(proxy);
  328.             }
  329.             this.httpConn = (HttpURLConnection) connection;
  330.            
  331.            
  332.             // Imposta Contesto SSL se attivo
  333.             if(this.sslContextProperties!=null){
  334.                 HttpsURLConnection httpsConn = (HttpsURLConnection) this.httpConn;
  335.                 SSLSocketFactory sslSocketFactory = buildSSLContextFactory();
  336.                 if(this.debug) {
  337.                     String clientCertificateConfigurated = this.sslContextProperties.getKeyStoreLocation();
  338.                     sslSocketFactory = new WrappedLogSSLSocketFactory(sslSocketFactory,
  339.                             this.logger.getLogger(), this.logger.buildMsg(""),
  340.                             clientCertificateConfigurated);
  341.                 }      
  342.                 httpsConn.setSSLSocketFactory(sslSocketFactory);
  343.                
  344.                 StringBuilder bfLog = new StringBuilder();
  345.                 HostnameVerifier hostnameVerifier = SSLUtilities.generateHostnameVerifier(this.sslContextProperties, bfLog,
  346.                         this.logger.getLogger(), this.loader);
  347.                 if(this.debug)
  348.                     this.logger.debug(bfLog.toString());
  349.                 if(hostnameVerifier!=null){
  350.                     httpsConn.setHostnameVerifier(hostnameVerifier);
  351.                 }
  352.             }
  353.             else {
  354.                 if(this.debug && (this.httpConn instanceof HttpsURLConnection)) {
  355.                     HttpsURLConnection httpsConn = (HttpsURLConnection) this.httpConn;
  356.                     if(httpsConn.getSSLSocketFactory()!=null) {
  357.                         SSLSocketFactory sslSocketFactory = httpsConn.getSSLSocketFactory();
  358.                         String clientCertificateConfigurated = SSLUtilities.getJvmHttpsClientCertificateConfigurated();
  359.                         sslSocketFactory = new WrappedLogSSLSocketFactory(sslSocketFactory,
  360.                                 this.logger.getLogger(), this.logger.buildMsg(""),
  361.                                 clientCertificateConfigurated);
  362.                         httpsConn.setSSLSocketFactory(sslSocketFactory);
  363.                     }
  364.                 }
  365.             }

  366.            
  367.             // Gestione automatica del redirect
  368.             // The HttpURLConnection‘s follow redirect is just an indicator, in fact it won’t help you to do the “real” http redirection, you still need to handle it manually.
  369.             /*
  370.             if(followRedirect){
  371.                 this.httpConn.setInstanceFollowRedirects(true);
  372.             }
  373.             */
  374.             // Deve essere impostato a false, altrimenti nel caso si intenda leggere gli header o l'input stream di un 302
  375.             // si ottiene il seguente errore:
  376.             //    java.net.HttpRetryException: cannot retry due to redirection, in streaming mode
  377.             this.httpConn.setInstanceFollowRedirects(false);

  378.            
  379.            
  380.             // Tipologia di servizio
  381.             MessageType requestMessageType = this.requestMsg.getMessageType();
  382.             OpenSPCoop2SoapMessage soapMessageRequest = null;
  383.             if(this.debug)
  384.                 this.logger.debug("Tipologia Servizio: "+this.requestMsg.getServiceBinding());
  385.             if(this.isSoap){
  386.                 soapMessageRequest = this.requestMsg.castAsSoap();
  387.             }
  388.            
  389.            
  390.             // Alcune implementazioni richiedono di aggiornare il Content-Type
  391.             this.requestMsg.updateContentType();
  392.            
  393.            
  394.            
  395.             // Proxy Authentication BASIC
  396.             if(this.proxyType!=null && this.proxyUsername!=null){
  397.                 if(this.debug)
  398.                     this.logger.debug("Impostazione autenticazione per proxy (username["+this.proxyUsername+"] password["+this.proxyPassword+"]) ...");
  399.                 if(this.proxyUsername!=null && this.proxyPassword!=null){
  400.                     String authentication = this.proxyUsername + ":" + this.proxyPassword;
  401.                     authentication = HttpConstants.AUTHORIZATION_PREFIX_BASIC + Base64Utilities.encodeAsString(authentication.getBytes());
  402.                     setRequestHeader(HttpConstants.PROXY_AUTHORIZATION,authentication, propertiesTrasportoDebug);
  403.                     if(this.debug)
  404.                         this.logger.info("Impostazione autenticazione per proxy (username["+this.proxyUsername+"] password["+this.proxyPassword+"]) ["+authentication+"]",false);
  405.                 }
  406.             }
  407.            
  408.            
  409.                    
  410.             // Impostazione Content-Type della Spedizione su HTTP          
  411.             String contentTypeRichiesta = null;
  412.             if(this.debug)
  413.                 this.logger.debug("Impostazione content type...");
  414.             if(this.isSoap){
  415.                 if(this.sbustamentoSoap && soapMessageRequest.countAttachments()>0 && TunnelSoapUtils.isTunnelOpenSPCoopSoap(soapMessageRequest)){
  416.                     contentTypeRichiesta = TunnelSoapUtils.getContentTypeTunnelOpenSPCoopSoap(soapMessageRequest.getSOAPBody());
  417.                 }else{
  418.                     contentTypeRichiesta = this.requestMsg.getContentType();
  419.                 }
  420.                 if(contentTypeRichiesta==null){
  421.                     throw new Exception("Content-Type del messaggio da spedire non definito");
  422.                 }
  423.             }
  424.             else{
  425.                 contentTypeRichiesta = this.requestMsg.getContentType();
  426.                 // Content-Type non obbligatorio in REST
  427.             }
  428.             if(this.debug)
  429.                 this.logger.info("Impostazione http Content-Type ["+contentTypeRichiesta+"]",false);
  430.             if(contentTypeRichiesta!=null){
  431.                 setRequestHeader(HttpConstants.CONTENT_TYPE,contentTypeRichiesta, propertiesTrasportoDebug);
  432.             }
  433.            
  434.            
  435.             // HttpMethod
  436.             if(this.httpMethod==null){
  437.                 throw new Exception("HttpRequestMethod non definito");
  438.             }

  439.            
  440.             // Impostazione transfer-length
  441.             if(this.debug)
  442.                 this.logger.debug("Impostazione transfer-length...");          
  443.             if(TransferLengthModes.TRANSFER_ENCODING_CHUNKED.equals(this.tlm)){
  444.                 HttpUtilities.setChunkedStreamingMode(this.httpConn, this.chunkLength, this.httpMethod, contentTypeRichiesta);
  445.                 //this.httpConn.setChunkedStreamingMode(chunkLength);
  446.             }
  447.             if(this.debug)
  448.                 this.logger.info("Impostazione transfer-length effettuata (chunkLength:"+this.chunkLength+"): "+this.tlm,false);
  449.            
  450.            
  451.             // Impostazione timeout
  452.             if(this.debug)
  453.                 this.logger.debug("Impostazione timeout...");
  454.             if(this.properties.get(CostantiConnettori.CONNETTORE_CONNECTION_TIMEOUT)!=null){
  455.                 try{
  456.                     connectionTimeout = Integer.parseInt(this.properties.get(CostantiConnettori.CONNETTORE_CONNECTION_TIMEOUT));
  457.                     connectionTimeoutConfigurazioneGlobale = this.properties.containsKey(CostantiConnettori.CONNETTORE_CONNECTION_TIMEOUT_GLOBALE);
  458.                 }catch(Exception e){
  459.                     this.logger.error("Parametro '"+CostantiConnettori.CONNETTORE_CONNECTION_TIMEOUT+"' errato",e);
  460.                 }
  461.             }
  462.             if(connectionTimeout==-1){
  463.                 connectionTimeout = HttpUtilities.HTTP_CONNECTION_TIMEOUT;
  464.             }
  465.             if(this.properties.get(CostantiConnettori.CONNETTORE_READ_CONNECTION_TIMEOUT)!=null){
  466.                 try{
  467.                     readConnectionTimeout = Integer.parseInt(this.properties.get(CostantiConnettori.CONNETTORE_READ_CONNECTION_TIMEOUT));
  468.                     readConnectionTimeoutConfigurazioneGlobale = this.properties.containsKey(CostantiConnettori.CONNETTORE_READ_CONNECTION_TIMEOUT_GLOBALE);
  469.                 }catch(Exception e){
  470.                     this.logger.error("Parametro "+CostantiConnettori.CONNETTORE_READ_CONNECTION_TIMEOUT+" errato",e);
  471.                 }
  472.             }
  473.             if(readConnectionTimeout==-1){
  474.                 readConnectionTimeout = HttpUtilities.HTTP_READ_CONNECTION_TIMEOUT;
  475.             }
  476.             if(this.debug)
  477.                 this.logger.info("Impostazione http timeout CT["+connectionTimeout+"] RT["+readConnectionTimeout+"]",false);
  478.             this.httpConn.setConnectTimeout(connectionTimeout);
  479.             this.httpConn.setReadTimeout(readConnectionTimeout);


  480.            
  481.             // Authentication BASIC
  482.             if(this.debug)
  483.                 this.logger.debug("Impostazione autenticazione...");
  484.             String user = null;
  485.             String password = null;
  486.             if(this.credenziali!=null){
  487.                 user = this.credenziali.getUser();
  488.                 password = this.credenziali.getPassword();
  489.             }else{
  490.                 user = this.properties.get(CostantiConnettori.CONNETTORE_USERNAME);
  491.                 password = this.properties.get(CostantiConnettori.CONNETTORE_PASSWORD);
  492.             }
  493.             if(user!=null && password!=null){
  494.                 String authentication = user + ":" + password;
  495.                 authentication = HttpConstants.AUTHORIZATION_PREFIX_BASIC + Base64Utilities.encodeAsString(authentication.getBytes());
  496.                 setRequestHeader(HttpConstants.AUTHORIZATION,authentication, propertiesTrasportoDebug);
  497.                 if(this.debug)
  498.                     this.logger.info("Impostazione autenticazione (username:"+user+" password:"+password+") ["+authentication+"]",false);
  499.             }

  500.            
  501.             // Authentication Token
  502.             NameValue nv = this.getTokenHeader();
  503.             if(nv!=null) {
  504.                 if(this.requestMsg!=null && this.requestMsg.getTransportRequestContext()!=null) {
  505.                     this.requestMsg.getTransportRequestContext().removeHeader(nv.getName()); // Fix: senno sovrascriveva il vecchio token
  506.                 }
  507.                 setRequestHeader(nv.getName(),nv.getValue(), propertiesTrasportoDebug);
  508.                 if(this.debug)
  509.                     this.logger.info("Impostazione autenticazione token (header-name '"+nv.getName()+"' value '"+nv.getValue()+"')",false);
  510.             }
  511.            
  512.            
  513.            
  514.             // Authentication Api Key
  515.             String apiKey = this.properties.get(CostantiConnettori.CONNETTORE_APIKEY);
  516.             if(apiKey!=null && StringUtils.isNotEmpty(apiKey)){
  517.                 String apiKeyHeader = this.properties.get(CostantiConnettori.CONNETTORE_APIKEY_HEADER);
  518.                 if(apiKeyHeader==null || StringUtils.isEmpty(apiKeyHeader)) {
  519.                     apiKeyHeader = CostantiConnettori.DEFAULT_HEADER_API_KEY;
  520.                 }
  521.                 setRequestHeader(apiKeyHeader,apiKey, propertiesTrasportoDebug);
  522.                 if(this.debug)
  523.                     this.logger.info("Impostazione autenticazione api key ["+apiKeyHeader+"]=["+apiKey+"]",false);
  524.                
  525.                 String appId = this.properties.get(CostantiConnettori.CONNETTORE_APIKEY_APPID);
  526.                 if(appId!=null && StringUtils.isNotEmpty(appId)){
  527.                     String appIdHeader = this.properties.get(CostantiConnettori.CONNETTORE_APIKEY_APPID_HEADER);
  528.                     if(appIdHeader==null || StringUtils.isEmpty(appIdHeader)) {
  529.                         appIdHeader = CostantiConnettori.DEFAULT_HEADER_APP_ID;
  530.                     }
  531.                     setRequestHeader(appIdHeader,appId, propertiesTrasportoDebug);
  532.                     if(this.debug)
  533.                         this.logger.info("Impostazione autenticazione api key (app id) ["+appIdHeader+"]=["+appId+"]",false);
  534.                 }
  535.             }
  536.            
  537.            
  538.             // ForwardProxy
  539.             if(this.forwardProxy_headerName!=null && this.forwardProxy_headerValue!=null) {
  540.                 if(this.requestMsg!=null && this.requestMsg.getTransportRequestContext()!=null) {
  541.                     this.requestMsg.getTransportRequestContext().removeHeader(this.forwardProxy_headerName); // Fix: senno sovrascriveva il vecchio token
  542.                 }
  543.                 setRequestHeader(this.forwardProxy_headerName,this.forwardProxy_headerValue, propertiesTrasportoDebug);
  544.                 if(this.debug)
  545.                     this.logger.info("Impostazione ForwardProxy (header-name '"+this.forwardProxy_headerName+"' value '"+this.forwardProxy_headerValue+"')",false);
  546.             }
  547.            
  548.            
  549.             // Impostazione Proprieta del trasporto
  550.             if(this.debug)
  551.                 this.logger.debug("Impostazione header di trasporto...");
  552.             this.forwardHttpRequestHeader();
  553.             if(this.propertiesTrasporto != null){
  554.                 Iterator<String> keys = this.propertiesTrasporto.keySet().iterator();
  555.                 while (keys.hasNext()) {
  556.                     String key = (String) keys.next();
  557.                     List<String> values = this.propertiesTrasporto.get(key);
  558.                     if(this.debug) {
  559.                         if(values!=null && !values.isEmpty()) {
  560.                             for (String value : values) {
  561.                                 this.logger.info("Set Transport Header ["+key+"]=["+value+"]",false);
  562.                             }
  563.                         }
  564.                     }
  565.                    
  566.                     if(this.encodingRFC2047){
  567.                         List<String> valuesEncoded = new ArrayList<>();
  568.                         if(values!=null && !values.isEmpty()) {
  569.                             for (String value : values) {
  570.                                 if(RFC2047Utilities.isAllCharactersInCharset(value, this.charsetRFC2047)==false){
  571.                                     String encoded = RFC2047Utilities.encode(new String(value), this.charsetRFC2047, this.encodingAlgorithmRFC2047);
  572.                                     //System.out.println("@@@@ CODIFICA ["+value+"] in ["+encoded+"]");
  573.                                     if(this.debug)
  574.                                         this.logger.info("RFC2047 Encoded value in ["+encoded+"] (charset:"+this.charsetRFC2047+" encoding-algorithm:"+this.encodingAlgorithmRFC2047+")",false);
  575.                                     valuesEncoded.add(encoded);
  576.                                 }
  577.                                 else{
  578.                                     valuesEncoded.add(value);
  579.                                 }
  580.                             }
  581.                         }
  582.                         setRequestHeader(this.validazioneHeaderRFC2047, key, valuesEncoded, this.logger, propertiesTrasportoDebug);
  583.                     }
  584.                     else{
  585.                         setRequestHeader(this.validazioneHeaderRFC2047, key, values, this.logger, propertiesTrasportoDebug);
  586.                     }
  587.                 }
  588.             }
  589.            
  590.            
  591.             // Aggiunga del SoapAction Header in caso di richiesta SOAP
  592.             // spostato sotto il forwardHeader per consentire alle trasformazioni di modificarla
  593.             if(this.isSoap && this.sbustamentoSoap == false){
  594.                 if(this.debug)
  595.                     this.logger.debug("Impostazione soap action...");
  596.                 boolean existsTransportProperties = false;
  597.                 if(TransportUtils.containsKey(this.propertiesTrasporto, Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION)){
  598.                     this.soapAction = TransportUtils.getFirstValue(this.propertiesTrasporto, Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION);
  599.                     existsTransportProperties = (this.soapAction!=null);
  600.                 }
  601.                 if(!existsTransportProperties) {
  602.                     this.soapAction = soapMessageRequest.getSoapAction();
  603.                 }
  604.                 if(this.soapAction==null){
  605.                     this.soapAction="\"OpenSPCoop\"";
  606.                 }
  607.                 if(MessageType.SOAP_11.equals(this.requestMsg.getMessageType()) && !existsTransportProperties){
  608.                     // NOTA non quotare la soap action, per mantenere la trasparenza della PdD
  609.                     setRequestHeader(Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION,this.soapAction, propertiesTrasportoDebug);
  610.                 }
  611.                 if(this.debug)
  612.                     this.logger.info("SOAP Action inviata ["+this.soapAction+"]",false);
  613.             }
  614.            
  615.            
  616.            
  617.             // Impostazione Metodo
  618.             if(this.debug)
  619.                 this.logger.info("Impostazione "+this.httpMethod+"...",false);
  620.             HttpUtilities.setStream(this.httpConn, this.httpMethod, contentTypeRichiesta);
  621.             HttpBodyParameters httpBody = new  HttpBodyParameters(this.httpMethod, contentTypeRichiesta);
  622. //          this.httpConn.setRequestMethod( method );
  623. //          this.httpConn.setDoOutput(false);
  624. //          this.httpConn.setDoInput(true);

  625.            
  626.             // Spedizione byte
  627.             boolean httpBody_isDoOutput = httpBody.isDoOutput();
  628.             if(!httpBody.isDoOutput() && request.isForceSendContent()) {
  629.                 this.httpConn.setDoOutput(true);
  630.                 httpBody_isDoOutput = true;
  631.             }
  632.             if(httpBody_isDoOutput){
  633.                 boolean consumeRequestMessage = true;
  634.                 if(this.followRedirects){
  635.                     consumeRequestMessage = false;
  636.                 }
  637.                 if(this.debug)
  638.                     this.logger.debug("Spedizione byte (consume-request-message:"+consumeRequestMessage+")...");
  639.                 OutputStream out = this.httpConn.getOutputStream();
  640.                 if(this.isDumpBinarioRichiesta()) {
  641.                     DumpByteArrayOutputStream bout = new DumpByteArrayOutputStream(this.dumpBinario_soglia, this.dumpBinario_repositoryFile, this.idTransazione,
  642.                             TipoMessaggio.RICHIESTA_USCITA_DUMP_BINARIO.getValue());
  643.                     try {
  644.                         this.emitDiagnosticStartDumpBinarioRichiestaUscita();
  645.                        
  646.                         if(this.isSoap && this.sbustamentoSoap){
  647.                             this.logger.debug("Sbustamento...");
  648.                             TunnelSoapUtils.sbustamentoMessaggio(soapMessageRequest,bout);
  649.                         }else{
  650.                             this.requestMsg.writeTo(bout, consumeRequestMessage);
  651.                         }
  652.                         bout.flush();
  653.                         bout.close();

  654.                         if(bout.isSerializedOnFileSystem()) {
  655.                             try(FileInputStream fin = new FileInputStream(bout.getSerializedFile())) {
  656.                                 Utilities.copy(fin, out);
  657.                             }
  658.                         }
  659.                         else {
  660.                             out.write(bout.toByteArray());
  661.                         }
  662.                        
  663.                         out.flush();
  664.                         out.close();
  665.                        
  666.                         this.dataRichiestaInoltrata = DateManager.getDate();
  667.                        
  668.                         this.dumpBinarioRichiestaUscita(bout, requestMessageType, contentTypeRichiesta, this.location, propertiesTrasportoDebug);
  669.                     }finally {
  670.                         try {
  671.                             bout.clearResources();
  672.                         }catch(Throwable t) {
  673.                             this.logger.error("Release resources failed: "+t.getMessage(),t);
  674.                         }
  675.                     }
  676.                 }else{
  677.                     if(this.isSoap && this.sbustamentoSoap){
  678.                         if(this.debug)
  679.                             this.logger.debug("Sbustamento...");
  680.                         TunnelSoapUtils.sbustamentoMessaggio(soapMessageRequest,out);
  681.                     }else{
  682.                         this.requestMsg.writeTo(out, consumeRequestMessage);
  683.                     }
  684.                    
  685.                     out.flush();
  686.                     out.close();
  687.                    
  688.                     this.dataRichiestaInoltrata = DateManager.getDate();
  689.                 }

  690.             }
  691.             else {
  692.                 if(this.isDumpBinarioRichiesta()) {
  693.                     // devo registrare almeno gli header HTTP
  694.                     this.emitDiagnosticStartDumpBinarioRichiestaUscita();
  695.                     this.dumpBinarioRichiestaUscita(null, null, null, this.location, propertiesTrasportoDebug);
  696.                 }
  697.             }
  698.            

  699.             // Analisi MimeType e ContentLocation della risposta
  700.             if(this.debug)
  701.                 this.logger.debug("Analisi risposta...");
  702.             Map<String, List<String>> mapHeaderHttpResponse = this.httpConn.getHeaderFields();
  703.             boolean protocolHttp10 = false;
  704.             if(mapHeaderHttpResponse!=null && mapHeaderHttpResponse.size()>0){
  705.                 if(this.propertiesTrasportoRisposta==null){
  706.                     this.propertiesTrasportoRisposta = new HashMap<>();
  707.                 }
  708.                 Iterator<String> itHttpResponse = mapHeaderHttpResponse.keySet().iterator();
  709.                 while(itHttpResponse.hasNext()){
  710.                     String keyHttpResponse = itHttpResponse.next();
  711.                     List<String> valueHttpResponse = mapHeaderHttpResponse.get(keyHttpResponse);
  712.                     if(valueHttpResponse!=null) {
  713.                         for(int i=0;i<valueHttpResponse.size();i++){
  714.                             if(this.debug)
  715.                                 this.logger.debug("HTTP risposta ["+keyHttpResponse+"] ["+valueHttpResponse.get(i)+"]...");
  716.                         }
  717.                     }
  718.                     if(keyHttpResponse==null){ // Check per evitare la coppia che ha come chiave null e come valore HTTP OK 200
  719.                         keyHttpResponse=HttpConstants.RETURN_CODE;
  720.                         // es. HTTP/1.1 200 OK
  721.                         if(valueHttpResponse!=null && valueHttpResponse.contains("/1.0")) {
  722.                             protocolHttp10 = true;
  723.                         }
  724.                     }
  725.                     this.propertiesTrasportoRisposta.put(keyHttpResponse, valueHttpResponse);
  726.                 }
  727.             }
  728.            
  729.             // KeepAlive
  730.             this.setKeepAlive(protocolHttp10, TransportUtils.getObjectAsString(mapHeaderHttpResponse, HttpConstants.CONNECTION));
  731.            
  732.             // TipoRisposta
  733.             this.tipoRisposta = TransportUtils.getObjectAsString(mapHeaderHttpResponse, HttpConstants.CONTENT_TYPE);
  734.            
  735.             // ContentLength della risposta
  736.             String contentLenghtString = TransportUtils.getObjectAsString(mapHeaderHttpResponse, HttpConstants.CONTENT_LENGTH);
  737.             if(contentLenghtString!=null){
  738.                 this.contentLength = Integer.valueOf(contentLenghtString);
  739.             }
  740.             else{
  741.                 if(this.httpConn.getContentLength()>0){
  742.                     this.contentLength = this.httpConn.getContentLength();
  743.                 }
  744.             }      
  745.            
  746.        
  747.             // Parametri di imbustamento
  748.             if(this.isSoap){
  749.                 this.imbustamentoConAttachment = false;
  750.                 if("true".equals(TransportUtils.getObjectAsString(mapHeaderHttpResponse, this.openspcoopProperties.getTunnelSOAPKeyWord_headerTrasporto()))){
  751.                     this.imbustamentoConAttachment = true;
  752.                 }
  753.                 this.mimeTypeAttachment = TransportUtils.getObjectAsString(mapHeaderHttpResponse, this.openspcoopProperties.getTunnelSOAPKeyWordMimeType_headerTrasporto());
  754.                 if(this.mimeTypeAttachment==null)
  755.                     this.mimeTypeAttachment = HttpConstants.CONTENT_TYPE_OPENSPCOOP2_TUNNEL_SOAP;
  756.                 //System.out.println("IMB["+imbustamentoConAttachment+"] MIME["+mimeTypeAttachment+"]");
  757.             }

  758.             // Ricezione Risposta
  759.             if(this.debug)
  760.                 this.logger.debug("Analisi risposta input stream e risultato http...");
  761.             this.initConfigurationAcceptOnlyReturnCode_202_200();
  762.            
  763.             // return code
  764.             this.codice = this.httpConn.getResponseCode();
  765.             this.resultHTTPMessage = this.httpConn.getResponseMessage();
  766.            
  767.             if(this.codice>=400){
  768.                 this.isResponse = this.httpConn.getErrorStream();
  769.             }
  770.             else{
  771.                 if(this.codice>299){
  772.                    
  773.                     String redirectLocation = TransportUtils.getObjectAsString(mapHeaderHttpResponse, HttpConstants.REDIRECT_LOCATION);
  774.                    
  775.                     // 3XX
  776.                     if(this.followRedirects){
  777.                                
  778.                         if(redirectLocation==null){
  779.                             throw new Exception("Non è stato rilevato l'header HTTP ["+HttpConstants.REDIRECT_LOCATION+"] necessario alla gestione del Redirect (code:"+this.codice+")");
  780.                         }
  781.                        
  782.                         TransportUtils.removeObject(request.getConnectorProperties(), CostantiConnettori.CONNETTORE_LOCATION);
  783.                         TransportUtils.removeObject(request.getConnectorProperties(), CostantiConnettori.CONNETTORE_HTTP_REDIRECT_NUMBER);
  784.                         TransportUtils.removeObject(request.getConnectorProperties(), CostantiConnettori.CONNETTORE_HTTP_REDIRECT_ROUTE);
  785.                         request.getConnectorProperties().put(CostantiConnettori.CONNETTORE_LOCATION, redirectLocation);
  786.                         request.getConnectorProperties().put(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_NUMBER, (this.numberRedirect+1)+"" );
  787.                         if(this.routeRedirect!=null){
  788.                             request.getConnectorProperties().put(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_ROUTE, this.routeRedirect+" -> "+redirectLocation );
  789.                         }else{
  790.                             request.getConnectorProperties().put(CostantiConnettori.CONNETTORE_HTTP_REDIRECT_ROUTE, redirectLocation );
  791.                         }
  792.                         if(this.originalAbsolutePrefixForRelativeRedirectLocation==null) {
  793.                             this.originalAbsolutePrefixForRelativeRedirectLocation = url.getProtocol()+"://"+url.getHost()+":"+url.getPort();
  794.                         }
  795.                         this.redirectLocation = redirectLocation; // per la prossima build()
  796.                         if(this.redirectLocation.startsWith("/")) {
  797.                             // relative
  798.                             this.redirectLocation = this.originalAbsolutePrefixForRelativeRedirectLocation + this.redirectLocation;
  799.                         }
  800.                        
  801.                         this.logger.warn("(hope:"+(this.numberRedirect+1)+") Redirect verso ["+redirectLocation+"] ...");
  802.                        
  803.                         if(this.numberRedirect==this.maxNumberRedirects){
  804.                             throw new Exception("Gestione redirect (code:"+this.codice+" "+HttpConstants.REDIRECT_LOCATION+":"+redirectLocation+") non consentita ulteriormente, sono già stati gestiti "+this.maxNumberRedirects+" redirects: "+this.routeRedirect);
  805.                         }
  806.                        
  807.                         boolean acceptOnlyReturnCode_307 = false;
  808.                         if(this.isSoap) {
  809.                             if(ConsegnaContenutiApplicativi.ID_MODULO.equals(this.idModulo)){
  810.                                 acceptOnlyReturnCode_307 = this.openspcoopProperties.isAcceptOnlyReturnCode_307_consegnaContenutiApplicativi();
  811.                             }
  812.                             else{
  813.                                 // InoltroBuste e InoltroRisposte
  814.                                 acceptOnlyReturnCode_307 = this.openspcoopProperties.isAcceptOnlyReturnCode_307_inoltroBuste();
  815.                             }
  816.                         }
  817.                         if(acceptOnlyReturnCode_307){
  818.                             if(this.codice!=307){
  819.                                 throw new Exception("Return code ["+this.codice+"] (redirect "+HttpConstants.REDIRECT_LOCATION+":"+redirectLocation+") non consentito dal WS-I Basic Profile (http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html#HTTP_Redirect_Status_Codes)");
  820.                             }
  821.                         }
  822.                         // Annullo precedente immagine
  823.                         this.clearRequestHeader();
  824.                         if(this.propertiesTrasportoRisposta!=null) {
  825.                             this.propertiesTrasportoRisposta.clear();
  826.                         }
  827.                         this.contentLength = -1;
  828.                         try {
  829.                             return this.send(request); // caching ricorsivo non serve
  830.                         }finally {
  831.                             /*System.out.println("CHECK ["+redirectLocation+"]");
  832.                             if(this.responseMsg!=null) {
  833.                                 System.out.println("MSG ["+this.responseMsg.getContentType()+"]");
  834.                                 this.responseMsg.writeTo(System.out, false);
  835.                             }*/
  836.                         }
  837.                        
  838.                     }else{
  839.                         if(this.isSoap) {
  840.                             throw new Exception("Gestione redirect (code:"+this.codice+" "+HttpConstants.REDIRECT_LOCATION+":"+redirectLocation+") non attiva");
  841.                         }
  842.                         else {
  843.                             this.logger.debug("Gestione redirect (code:"+this.codice+" "+HttpConstants.REDIRECT_LOCATION+":"+redirectLocation+") non attiva");
  844.                            
  845.                             if(this.location!=null && redirectLocation!=null){
  846.                                 this.location = this.location+" [redirect-location: "+redirectLocation+"]";
  847.                             }
  848.                            
  849.                             if(httpBody.isDoInput()){
  850.                                 this.isResponse = this.httpConn.getInputStream();
  851.                                 if(this.isResponse==null) {
  852.                                     this.isResponse = this.httpConn.getErrorStream();
  853.                                 }
  854.                             }
  855.                         }
  856.                     }
  857.                 }
  858.                 else{
  859.                     if(this.isSoap && this.acceptOnlyReturnCode_202_200){
  860.                         if(this.codice!=200 && this.codice!=202){
  861.                             throw new Exception("Return code ["+this.codice+"] non consentito dal WS-I Basic Profile (http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html#HTTP_Success_Status_Codes)");
  862.                         }
  863.                     }
  864.                     if(httpBody.isDoInput()){
  865.                         this.isResponse = this.httpConn.getInputStream();
  866.                     }
  867.                 }
  868.             }
  869.            

  870.            
  871.             /* ------------  PostOutRequestHandler ------------- */
  872.             this.postOutRequest();
  873.            
  874.            
  875.            
  876.            
  877.             /* ------------  PreInResponseHandler ------------- */
  878.             this.preInResponse();
  879.            
  880.             // Lettura risposta parametri NotifierInputStream per la risposta
  881.             this.notifierInputStreamParams = null;
  882.             if(this.preInResponseContext!=null){
  883.                 this.notifierInputStreamParams = this.preInResponseContext.getNotifierInputStreamParams();
  884.             }
  885.            
  886.            
  887.             /* ------------  Gestione Risposta ------------- */
  888.            
  889.             this.normalizeInputStreamResponse(readConnectionTimeout, readConnectionTimeoutConfigurazioneGlobale);
  890.            
  891.             this.initCheckContentTypeConfiguration();
  892.            
  893.             if(this.isDumpBinarioRisposta()){
  894.                 if(!this.dumpResponse(this.propertiesTrasportoRisposta)) {
  895.                     return false;
  896.                 }
  897.             }
  898.            
  899.             if(this.isRest){
  900.                            
  901.                 if(this.doRestResponse()==false){
  902.                     return false;
  903.                 }
  904.                
  905.             }
  906.             else{
  907.            
  908.                 if(this.doSoapResponse()==false){
  909.                     return false;
  910.                 }
  911.                
  912.             }

  913.             if(this.debug)
  914.                 this.logger.info("Gestione invio/risposta http effettuata con successo",false);
  915.            
  916.             return true;

  917.         }  catch(Exception e){
  918.             this.eccezioneProcessamento = e;
  919.             String msgErrore = this.readExceptionMessageFromException(e);
  920.             if(this.generateErrorWithConnectorPrefix) {
  921.                 this.errore = "Errore avvenuto durante la consegna HTTP: "+msgErrore;
  922.             }
  923.             else {
  924.                 this.errore = msgErrore;
  925.             }
  926.             this.logger.error("Errore avvenuto durante la consegna HTTP: "+msgErrore,e);

  927.             this.processConnectionTimeoutException(connectionTimeout, connectionTimeoutConfigurazioneGlobale, e, msgErrore);
  928.            
  929.             this.processReadTimeoutException(readConnectionTimeout, readConnectionTimeoutConfigurazioneGlobale, e, msgErrore);
  930.            
  931.             return false;
  932.         }
  933.     }
  934.    
  935.     /**
  936.      * Effettua la disconnessione
  937.      */
  938.     @Override
  939.     public void disconnect() throws ConnettoreException{
  940.         List<Throwable> listExceptionChiusura = new ArrayList<Throwable>();
  941.         try{
  942.             // Gestione finale della connessione
  943.             if(this.isResponse!=null){
  944.                 if(this.debug && this.logger!=null)
  945.                     this.logger.debug("Chiusura socket...");
  946.                 try {
  947.                     this.isResponse.close();
  948.                 }
  949.                 catch(Throwable t) {
  950.                     if(this.logger!=null) {
  951.                         this.logger.debug("Chiusura socket fallita: "+t.getMessage(),t);
  952.                     }
  953.                     listExceptionChiusura.add(t);
  954.                 }
  955.             }
  956.    
  957.             // fine HTTP.
  958.             if(this.httpConn!=null){
  959.                 if(this.debug && this.logger!=null)
  960.                     this.logger.debug("Chiusura connessione...");
  961.                 try {
  962.                     // FIX: https://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html
  963.                     /*
  964.                      * Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.
  965.                      * If getInputStream() successfully returns, read the entire response body.
  966.                      * When calling getInputStream() from HttpURLConnection, if an IOException occurs, catch the exception and call getErrorStream() to get the response body (if there is any).
  967.                      * Reading the response body cleans up the connection even if you are not interested in the response content itself. But if the response body is long and you are not interested in the rest of it after seeing the beginning, you can close the InputStream.
  968.                      * But you need to be aware that more data could be on its way. Thus the connection may not be cleared for reuse.
  969.                      *
  970.                      * (Quindi se keepAlive == true)
  971.                      * If client called HttpURLConnection.getInputSteam().close(),
  972.                      *    the later call to HttpURLConnection.disconnect() will NOT close the Socket. i.e. The Socket is reused (cached)
  973.                      * If client does not call close(), call disconnect() will close the InputStream and close the Socket.
  974.                      *
  975.                      * !!! So in order to reuse the Socket, just call InputStream.close(). Do not call HttpURLConnection.disconnect().
  976.                      *
  977.                      * */
  978.                     if(!this.keepAlive) {
  979.                         this.httpConn.disconnect();
  980.                     }
  981.                 }catch(Throwable t) {
  982.                     if(this.logger!=null) {
  983.                         this.logger.debug("Chiusura connessione fallita: "+t.getMessage(),t);
  984.                     }
  985.                     listExceptionChiusura.add(t);
  986.                 }
  987.             }
  988.            
  989.             // super.disconnect (Per risorse base)
  990.             try {
  991.                 super.disconnect();
  992.             }catch(Throwable t) {
  993.                 if(this.logger!=null) {
  994.                     this.logger.debug("Chiusura risorse fallita: "+t.getMessage(),t);
  995.                 }
  996.                 listExceptionChiusura.add(t);
  997.             }
  998.            
  999.         }catch(Exception e){
  1000.             throw new ConnettoreException("Chiusura connessione non riuscita: "+e.getMessage(),e);
  1001.         }
  1002.        
  1003.         if(listExceptionChiusura!=null && !listExceptionChiusura.isEmpty()) {
  1004.             org.openspcoop2.utils.UtilsMultiException multiException = new org.openspcoop2.utils.UtilsMultiException(listExceptionChiusura.toArray(new Throwable[1]));
  1005.             throw new ConnettoreException("Chiusura connessione non riuscita: "+multiException.getMessage(),multiException);
  1006.         }
  1007.     }

  1008.    
  1009.     private void setKeepAlive(boolean protocolHttp10, String connectionHeaderValue) {
  1010.         /* https://tools.ietf.org/html/rfc7230#section-6.3 */
  1011.         /*
  1012.         A recipient determines whether a connection is persistent or not
  1013.            based on the most recently received message's protocol version and
  1014.            Connection header field (if any):

  1015.            -  If the "close" connection option is present, the connection will
  1016.               not persist after the current response; else,

  1017.            -  If the received protocol is HTTP/1.1 (or later), the connection
  1018.               will persist after the current response; else,

  1019.            -  If the received protocol is HTTP/1.0, the "keep-alive" connection
  1020.               option is present, the recipient is not a proxy, and the recipient
  1021.               wishes to honor the HTTP/1.0 "keep-alive" mechanism, the
  1022.               connection will persist after the current response; otherwise,

  1023.            -  The connection will close after the current response.
  1024.          */
  1025.        
  1026.         if(HttpConstants.CONNECTION_VALUE_CLOSE.equalsIgnoreCase(connectionHeaderValue)) {
  1027.             this.keepAlive = false;
  1028.         }
  1029.         else if(!protocolHttp10) {
  1030.             this.keepAlive = true;
  1031.         }
  1032.         else if(connectionHeaderValue!=null){
  1033.             this.keepAlive = HttpConstants.CONNECTION_VALUE_KEEP_ALIVE.equalsIgnoreCase(connectionHeaderValue);
  1034.         }
  1035.         else {
  1036.             this.keepAlive = false;
  1037.         }
  1038.     }
  1039.    
  1040.     /**
  1041.      * Ritorna l'informazione su dove il connettore sta spedendo il messaggio
  1042.      *
  1043.      * @return location di inoltro del messaggio
  1044.      */
  1045.     @Override
  1046.     public String getLocation(){
  1047.         if(this.location==null){
  1048.             // può darsi che per un errore non sia ancora stata inizializzata la location
  1049.             try{
  1050.                 this.buildLocation();
  1051.             }catch(Throwable t){}
  1052.         }
  1053.         if(this.location!=null){
  1054.             String l = new String(this.location);
  1055.             if(this.routeRedirect!=null){
  1056.                 l = l+" [redirects route path: "+this.routeRedirect+"]";
  1057.             }
  1058.             if(this.proxyType!=null){
  1059.                 l = l+" [proxy: "+this.proxyHostname+":"+this.proxyPort+"]";
  1060.             }
  1061. //          if(this.forwardProxy!=null && this.forwardProxy.isEnabled()) {
  1062. //              l = l+" [govway-proxy]";
  1063. //          }
  1064.             return l;
  1065.         }
  1066.         return null;
  1067.     }
  1068.     private void buildLocation() throws ConnettoreException {
  1069.         if(this.redirectLocation!=null) {
  1070.             this.location = this.redirectLocation;
  1071.         }
  1072.         else {
  1073.             this.location = TransportUtils.getObjectAsString(this.properties,CostantiConnettori.CONNETTORE_LOCATION);
  1074.         }
  1075.         NameValue nv = this.getTokenQueryParameter();
  1076.         if(nv!=null) {
  1077.             if(this.requestMsg!=null && this.requestMsg.getTransportRequestContext()!=null) {
  1078.                 this.requestMsg.getTransportRequestContext().removeParameter(nv.getName()); // Fix: senno sovrascriveva il vecchio token
  1079.             }
  1080.             if(this.propertiesUrlBased==null) {
  1081.                 this.propertiesUrlBased = new HashMap<>();
  1082.             }
  1083.             TransportUtils.setParameter(this.propertiesUrlBased, nv.getName(), nv.getValue());
  1084.         }
  1085.         if(this.redirectLocation==null) {
  1086.             this.location = ConnettoreUtils.buildLocationWithURLBasedParameter(this.logger!=null ? this.logger.getLogger() : null, this.requestMsg,
  1087.                     this.connettoreHttps ? TipiConnettore.HTTPS.toString() : TipiConnettore.HTTP.toString(),
  1088.                     this.propertiesUrlBased, this.location,
  1089.                     this.getProtocolFactory(), this.idModulo);
  1090.         }
  1091.        
  1092.         this.updateLocation_forwardProxy(this.location);
  1093.     }
  1094.    

  1095.     private void setRequestHeader(boolean validazioneHeaderRFC2047, String key, List<String> values, ConnettoreLogger logger, Map<String, List<String>> propertiesTrasportoDebug) throws Exception {
  1096.        
  1097.         if(validazioneHeaderRFC2047){
  1098.             try{
  1099.                 RFC2047Utilities.validHeader(key, values);
  1100.                 setRequestHeader(key, values, propertiesTrasportoDebug);
  1101.             }catch(UtilsException e){
  1102.                 logger.error(e.getMessage(),e);
  1103.             }
  1104.         }
  1105.         else{
  1106.             setRequestHeader(key,values, propertiesTrasportoDebug);
  1107.         }
  1108.        
  1109.     }
  1110.    
  1111.     @Override
  1112.     protected void setRequestHeader(String key,List<String> values) throws Exception {
  1113.         if(values!=null && !values.isEmpty()) {
  1114.             for (String value : values) {
  1115.                 this.httpConn.addRequestProperty(key,value);        
  1116.             }
  1117.         }
  1118.     }

  1119. }


  1120. class HttpAuthenticator extends Authenticator{
  1121.    
  1122.     private String username;
  1123.     private String password;
  1124.    
  1125.     HttpAuthenticator(String u,String p){
  1126.         super();
  1127.         this.username = u;
  1128.         this.password = p;
  1129.     }
  1130.    
  1131.     @Override
  1132.     public PasswordAuthentication getPasswordAuthentication(){
  1133.         return new PasswordAuthentication(this.username, this.password.toCharArray());
  1134.     }
  1135. }