DumpRawConnectorOutMessage.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.services.connector.messages;

  21. import java.io.ByteArrayOutputStream;
  22. import java.io.File;
  23. import java.io.PrintWriter;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;

  28. import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
  29. import org.openspcoop2.message.OpenSPCoop2Message;
  30. import org.openspcoop2.message.OpenSPCoop2MessageProperties;
  31. import org.openspcoop2.message.OpenSPCoop2RestMessage;
  32. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  33. import org.openspcoop2.message.constants.MessageRole;
  34. import org.openspcoop2.message.constants.MessageType;
  35. import org.openspcoop2.message.constants.ServiceBinding;
  36. import org.openspcoop2.message.exception.ParseException;
  37. import org.openspcoop2.message.exception.ParseExceptionUtils;
  38. import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
  39. import org.openspcoop2.pdd.services.DumpRaw;
  40. import org.openspcoop2.pdd.services.connector.ConnectorException;
  41. import org.openspcoop2.protocol.sdk.Context;
  42. import org.openspcoop2.utils.io.DumpByteArrayOutputStream;
  43. import org.openspcoop2.utils.transport.TransportUtils;
  44. import org.slf4j.Logger;

  45. /**
  46.  * DumpRawConnectorOutMessage
  47.  *
  48.  * @author Poli Andrea (apoli@link.it)
  49.  * @author $Author$
  50.  * @version $Rev$, $Date$
  51.  */
  52. public class DumpRawConnectorOutMessage implements ConnectorOutMessage {

  53.     private Logger log;
  54.     private ConnectorOutMessage connectorOutMessage;
  55.     private DumpByteArrayOutputStream bout = null;
  56.     private MessageType messageType = null;
  57.     private ParseException parseException = null;
  58.     private Map<String, List<String>> trasporto = new HashMap<>();
  59.     private Integer contentLenght;
  60.     private String contentType;
  61.     private Integer status;
  62.     private OpenSPCoop2Properties openspcoopProperties;
  63.    
  64.     private Context context;
  65.     private String idTransazione;
  66.     private int soglia;
  67.     private File repositoryFile;
  68.    
  69.     private DumpRaw dumpRaw;
  70.    
  71.     public DumpRawConnectorOutMessage(Logger log,ConnectorOutMessage connectorOutMessage, Context context,
  72.             int soglia, File repositoryFile,
  73.             DumpRaw dump){
  74.         this.log = log;
  75.         this.connectorOutMessage = connectorOutMessage;
  76.         this.openspcoopProperties =  OpenSPCoop2Properties.getInstance();
  77.        
  78.         this.context = context;
  79.         if(this.context!=null) {
  80.             this.idTransazione = (String) this.context.getObject(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE);
  81.         }
  82.         this.soglia = soglia;
  83.         this.repositoryFile = repositoryFile;
  84.        
  85.         this.dumpRaw = dump;
  86.     }
  87.    
  88.     public ConnectorOutMessage getWrappedConnectorOutMessage() {
  89.         return this.connectorOutMessage;
  90.     }
  91.    
  92.     public DumpByteArrayOutputStream getDumpByteArrayOutputStream() {
  93.         if(this.bout!=null && this.bout.size()>0){
  94.             return this.bout;
  95.         }
  96.         return null;
  97.     }
  98. //  public byte[] getResponseAsByte(){
  99. //      if(this.bout!=null && this.bout.size()>0){
  100. //          return this.bout.toByteArray();
  101. //      }
  102. //      return null;
  103. //  }
  104. //  public String getResponseAsString(){
  105. //      if(this.bout!=null && this.bout.size()>0){
  106. //          return this.bout.toString();
  107. //      }
  108. //      return null;
  109. //  }
  110.     public MessageType getMessageType() {
  111.         return this.messageType;
  112.     }
  113.     public boolean isParsingResponseError(){
  114.         return this.parseException!=null;
  115.     }
  116.     public String getParsingResponseErrorAsString(){
  117.         if(this.parseException!=null){
  118.             try{
  119.                 ByteArrayOutputStream bout = new ByteArrayOutputStream();
  120.                 PrintWriter pw = new PrintWriter(bout);
  121.                 this.parseException.getSourceException().printStackTrace(pw);
  122.                 pw.flush();
  123.                 bout.flush();
  124.                 pw.close();
  125.                 bout.close();
  126.                 return bout.toString();
  127.             }catch(Exception e){
  128.                 return "ParsingResponseError, serializazione eccezione non riuscita: "+e.getMessage();
  129.             }
  130.         }
  131.         return null;
  132.     }
  133.    
  134.     public Map<String, List<String>> getTrasporto() {
  135.         return this.trasporto;
  136.     }

  137.     public Integer getContentLenght() {
  138.         return this.contentLenght;
  139.     }

  140.     public String getContentType() {
  141.         return this.contentType;
  142.     }
  143.     public Integer getStatus() {
  144.         return this.status;
  145.     }
  146.    
  147.     private boolean emitDiagnostic = false;
  148.     private void emitDiagnosticStartDumpBinarioRispostaUscita() {
  149.         if(this.dumpRaw!=null && !this.emitDiagnostic) {
  150.             this.emitDiagnostic = true;
  151.             this.dumpRaw.emitDiagnosticStartDumpBinarioRispostaUscita();
  152.         }
  153.     }
  154.    
  155.     private void _sendHeaders(OpenSPCoop2Message message) throws Exception {
  156.         if(message==null) {
  157.             throw new Exception("Message is null");
  158.         }
  159.         // Eventuali header http propagati
  160.         OpenSPCoop2MessageProperties forwardHeader = null;
  161.         if(ServiceBinding.REST.equals(message.getServiceBinding())) {
  162.             forwardHeader = message.getForwardTransportHeader(this.openspcoopProperties.getRESTServicesHeadersForwardConfig(false));
  163.         }
  164.         else {
  165.             forwardHeader = message.getForwardTransportHeader(this.openspcoopProperties.getSOAPServicesHeadersForwardConfig(false));
  166.         }
  167.         if(forwardHeader!=null && forwardHeader.size()>0){
  168.             Iterator<String> keys = forwardHeader.getKeys();
  169.             while (keys.hasNext()) {
  170.                 String key = (String) keys.next();
  171.                 List<String> values = forwardHeader.getPropertyValues(key);
  172.                 if(values!=null && !values.isEmpty()) {
  173.                     for (String value : values) {
  174.                         this.addHeader(key, value);        
  175.                     }
  176.                 }
  177.             }
  178.         }
  179.     }
  180.    
  181.     @Override
  182.     public void sendResponse(OpenSPCoop2Message message, boolean consume)
  183.             throws ConnectorException {
  184.        
  185.         emitDiagnosticStartDumpBinarioRispostaUscita();
  186.        
  187.         try{
  188.             // Propago eventuali header http
  189.             this._sendHeaders(message);
  190.            
  191.             // Prima lo registro e dopo serializzo
  192.             if(this.bout!=null){
  193.                 this.bout.clearResources();
  194.                 this.bout = null;
  195.             }
  196.             this.bout = new DumpByteArrayOutputStream(this.soglia, this.repositoryFile, this.idTransazione,
  197.                     TipoMessaggio.RISPOSTA_USCITA_DUMP_BINARIO.getValue());
  198.            
  199.             boolean hasContent = false;
  200.            
  201.             // il save e' necessario con i connettori in caso di errori di validazione
  202.             if(message!=null && ServiceBinding.SOAP.equals(message.getServiceBinding())){
  203.                 hasContent = true;
  204.                 OpenSPCoop2SoapMessage soap = message.castAsSoap();
  205.                 if(soap.hasSOAPFault()){
  206.                     soap.saveChanges();
  207.                 }
  208.             }
  209.             if(message!=null && ServiceBinding.REST.equals(message.getServiceBinding())){
  210.                 OpenSPCoop2RestMessage<?> rest = message.castAsRest();
  211.                 hasContent = rest.hasContent();
  212.             }
  213.            
  214.             if(hasContent) {
  215.                 message.writeTo(this.bout, consume);
  216.             }
  217.            
  218.             if(message!=null) {
  219.                 this.messageType = message.getMessageType();
  220.             }
  221.            
  222.         }catch(Throwable t){
  223.             this.bout = null;
  224.             if(message.getParseException()!=null){
  225.                 this.parseException = message.getParseException();
  226.             }
  227.             else{
  228.                 this.parseException = ParseExceptionUtils.buildParseException(t,MessageRole.RESPONSE);
  229.             }
  230.             this.log.error("SendResponse error: "+t.getMessage(),t);
  231.             // Devo lanciare l'eccezione senno il servizio esce con 200
  232.             throw new ConnectorException(this.parseException.getSourceException());
  233.         }finally{
  234.             try{
  235.                 if(this.bout!=null){
  236.                     this.bout.flush();
  237.                 }
  238.             }catch(Throwable close){}
  239.             try{
  240.                 if(this.bout!=null){
  241.                     this.bout.close();
  242.                 }
  243.             }catch(Throwable close){}
  244.         }
  245.        
  246.         // wrapped method
  247.         //this.connectorOutMessage.sendResponse(message, consume); Nel caso di attachments genera un nuovo boundary
  248.         if(this.bout!=null){
  249.             this.connectorOutMessage.sendResponse(this.bout);
  250.         }
  251.     }

  252.     @Override
  253.     public void sendResponse(DumpByteArrayOutputStream message) throws ConnectorException {
  254.    
  255.         emitDiagnosticStartDumpBinarioRispostaUscita();
  256.        
  257.         try{
  258.             // Prima lo registro e dopo serializzo
  259.             if(this.bout!=null){
  260.                 this.bout.clearResources();
  261.                 this.bout = null;
  262.             }
  263.             if(message!=null && message.size()>0) {
  264.                 this.bout = message;
  265.             }
  266.         }catch(Throwable t){
  267.             try{
  268.                 this.bout = DumpByteArrayOutputStream.newInstance(("SendResponse byte[] error: "+t.getMessage()).getBytes());
  269.             }catch(Throwable tWrite){}
  270.             this.log.error("SendResponse byte[] error: "+t.getMessage(),t);
  271.         }finally{
  272.             try{
  273.                 if(this.bout!=null){
  274.                     this.bout.flush();
  275.                 }
  276.             }catch(Throwable close){}
  277.             try{
  278.                 if(this.bout!=null){
  279.                     this.bout.close();
  280.                 }
  281.             }catch(Throwable close){}
  282.         }
  283.        
  284.         // wrapped method
  285.         this.connectorOutMessage.sendResponse(message);
  286.     }
  287.    
  288.     @Override
  289.     public void sendResponseHeaders(OpenSPCoop2Message message) throws ConnectorException{
  290.        
  291.         emitDiagnosticStartDumpBinarioRispostaUscita();
  292.        
  293.         try{
  294.             // Propago eventuali header http
  295.             this._sendHeaders(message);
  296.         }catch(Exception e){
  297.             throw new ConnectorException(e.getMessage(),e);
  298.         }
  299.     }

  300.     @Override
  301.     public void setHeader(String key, String value) throws ConnectorException {
  302.         try{
  303.             // Prima lo registro e dopo serializzo
  304.             TransportUtils.setHeader(this.trasporto, key, value);
  305.         }catch(Throwable t){
  306.             try{
  307.                 this.bout = DumpByteArrayOutputStream.newInstance(("setHeader ["+key+"] error: "+t.getMessage()).getBytes());
  308.             }catch(Throwable tWrite){}
  309.             this.log.error("Set Header ["+key+"]["+value+"] error: "+t.getMessage(),t);
  310.         }
  311.        
  312.         // wrapped method
  313.         this.connectorOutMessage.setHeader(key,value);
  314.     }
  315.     @Override
  316.     public void addHeader(String key, String value) throws ConnectorException {
  317.         try{
  318.             // Prima lo registro e dopo serializzo
  319.             TransportUtils.addHeader(this.trasporto, key, value);
  320.         }catch(Throwable t){
  321.             try{
  322.                 this.bout = DumpByteArrayOutputStream.newInstance(("addHeader ["+key+"] error: "+t.getMessage()).getBytes());
  323.             }catch(Throwable tWrite){}
  324.             this.log.error("Add Header ["+key+"]["+value+"] error: "+t.getMessage(),t);
  325.         }
  326.        
  327.         // wrapped method
  328.         this.connectorOutMessage.addHeader(key,value);
  329.     }

  330.     @Override
  331.     public void setContentLength(int length) throws ConnectorException {
  332.        
  333.         // Prima lo registro
  334.         this.contentLenght = length;
  335.        
  336.         // wrapped method
  337.         this.connectorOutMessage.setContentLength(length);
  338.     }

  339.     @Override
  340.     public void setContentType(String type) throws ConnectorException {
  341.        
  342.         // Prima lo registro
  343.         this.contentType = type;
  344.        
  345.         // wrapped method
  346.         this.connectorOutMessage.setContentType(type);
  347.     }

  348.     @Override
  349.     public void setStatus(int status) throws ConnectorException {
  350.    
  351.         // Prima lo registro
  352.         this.status = status;
  353.        
  354.         // wrapped method
  355.         this.connectorOutMessage.setStatus(status);
  356.     }

  357.    
  358.     // Wrapped Only
  359.    
  360.     @Override
  361.     public int getResponseStatus() throws ConnectorException {
  362.         // wrapped method
  363.         return this.connectorOutMessage.getResponseStatus();
  364.     }

  365.     @Override
  366.     public void flush(boolean throwException) throws ConnectorException {
  367.         // wrapped method
  368.         this.connectorOutMessage.flush(throwException);
  369.     }

  370.     @Override
  371.     public void close(boolean throwException) throws ConnectorException {
  372.         // wrapped method
  373.         this.connectorOutMessage.close(throwException);
  374.     }

  375. }