HttpServletConnectorInMessage.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.ByteArrayInputStream;
  22. import java.io.File;
  23. import java.io.FileInputStream;
  24. import java.io.IOException;
  25. import java.io.InputStream;
  26. import java.util.Date;
  27. import java.util.List;

  28. import javax.servlet.http.HttpServletRequest;

  29. import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
  30. import org.openspcoop2.message.OpenSPCoop2Message;
  31. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  32. import org.openspcoop2.message.OpenSPCoop2MessageParseResult;
  33. import org.openspcoop2.message.constants.MessageRole;
  34. import org.openspcoop2.message.constants.MessageType;
  35. import org.openspcoop2.message.exception.ParseExceptionUtils;
  36. import org.openspcoop2.message.soap.SoapUtils;
  37. import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
  38. import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
  39. import org.openspcoop2.pdd.core.CostantiPdD;
  40. import org.openspcoop2.pdd.core.controllo_traffico.DimensioneMessaggiUtils;
  41. import org.openspcoop2.pdd.core.controllo_traffico.LimitExceededNotifier;
  42. import org.openspcoop2.pdd.core.controllo_traffico.SogliaDimensioneMessaggio;
  43. import org.openspcoop2.pdd.core.controllo_traffico.SogliaReadTimeout;
  44. import org.openspcoop2.pdd.core.controllo_traffico.TimeoutNotifier;
  45. import org.openspcoop2.pdd.core.controllo_traffico.TimeoutNotifierType;
  46. import org.openspcoop2.pdd.logger.DiagnosticInputStream;
  47. import org.openspcoop2.pdd.logger.MsgDiagnosticiProperties;
  48. import org.openspcoop2.pdd.logger.MsgDiagnostico;
  49. import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
  50. import org.openspcoop2.pdd.services.connector.ConnectorException;
  51. import org.openspcoop2.protocol.sdk.Context;
  52. import org.openspcoop2.protocol.sdk.IProtocolFactory;
  53. import org.openspcoop2.protocol.sdk.constants.IDService;
  54. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  55. import org.openspcoop2.protocol.sdk.state.URLProtocolContext;
  56. import org.openspcoop2.utils.LimitExceededIOException;
  57. import org.openspcoop2.utils.LimitedInputStream;
  58. import org.openspcoop2.utils.LoggerWrapperFactory;
  59. import org.openspcoop2.utils.TimeoutInputStream;
  60. import org.openspcoop2.utils.Utilities;
  61. import org.openspcoop2.utils.UtilsRuntimeException;
  62. import org.openspcoop2.utils.date.DateManager;
  63. import org.openspcoop2.utils.io.DumpByteArrayOutputStream;
  64. import org.openspcoop2.utils.io.notifier.NotifierInputStreamParams;
  65. import org.openspcoop2.utils.transport.Credential;
  66. import org.openspcoop2.utils.transport.TransportUtils;
  67. import org.openspcoop2.utils.transport.http.HttpConstants;
  68. import org.slf4j.Logger;

  69. /**
  70.  * HttpServletConnectorInMessage
  71.  *
  72.  * @author Andrea Poli (apoli@link.it)
  73.  * @author $Author$
  74.  * @version $Rev$, $Date$
  75.  */
  76. public class HttpServletConnectorInMessage implements ConnectorInMessage {

  77.     protected RequestInfo requestInfo;
  78.     protected HttpServletRequest req;
  79.     protected OpenSPCoop2Properties openspcoopProperties;
  80.     protected OpenSPCoop2Message message;
  81.     protected InputStream is;
  82.     protected LimitedInputStream _limitedIS;
  83.     protected TimeoutInputStream _timeoutIS;
  84.     protected DiagnosticInputStream _diagnosticIS;
  85.     protected DumpByteArrayOutputStream buffer;
  86.     protected boolean buffered = false;
  87.     protected OpenSPCoop2MessageSoapStreamReader soapReader;
  88.     protected Logger log;
  89.     protected String idModulo;
  90.     private IDService idModuloAsIDService;
  91.     private MessageType requestMessageType;
  92.     protected Date dataIngressoRichiesta;

  93.     private Context context;
  94.     private String idTransazione;
  95.     private int soglia;
  96.     private File repositoryFile;
  97.    
  98.     private SogliaReadTimeout requestReadTimeout;
  99.     private SogliaDimensioneMessaggio requestLimitSize;
  100.     private boolean requestLimitSizeDisabled = false;
  101.    
  102.     private boolean useDiagnosticInputStream;
  103.     private MsgDiagnostico msgDiagnostico;
  104.    
  105.     public HttpServletConnectorInMessage(RequestInfo requestInfo, HttpServletRequest req,
  106.             IDService idModuloAsIDService, String idModulo) throws ConnectorException{
  107.         try{
  108.             this.requestInfo = requestInfo;
  109.             this.req = req;
  110.             this.openspcoopProperties = OpenSPCoop2Properties.getInstance();
  111.             this.is = this.req.getInputStream();
  112.            
  113.             this.log = OpenSPCoop2Logger.getLoggerOpenSPCoopCore();
  114.             if(this.log==null)
  115.                 this.log = LoggerWrapperFactory.getLogger(HttpServletConnectorInMessage.class);
  116.            
  117.             this.idModuloAsIDService = idModuloAsIDService;
  118.             this.idModulo = idModulo;
  119.            
  120.             if(IDService.PORTA_APPLICATIVA.equals(idModuloAsIDService) || IDService.PORTA_APPLICATIVA_NIO.equals(idModuloAsIDService)){
  121.                 this.requestMessageType = this.getRequestInfo().getProtocolRequestMessageType();
  122.             }
  123.             else{
  124.                 this.requestMessageType = this.getRequestInfo().getIntegrationRequestMessageType();
  125.             }
  126.            
  127.             if(this.openspcoopProperties!=null) {
  128.                 if(IDService.PORTA_APPLICATIVA.equals(idModuloAsIDService) || IDService.PORTA_APPLICATIVA_NIO.equals(idModuloAsIDService)){
  129.                     this.useDiagnosticInputStream = this.openspcoopProperties.isConnettoriUseDiagnosticInputStream_ricezioneBuste();
  130.                 }
  131.                 else {
  132.                     this.useDiagnosticInputStream = this.openspcoopProperties.isConnettoriUseDiagnosticInputStream_ricezioneContenutiApplicativi();
  133.                 }
  134.             }
  135.            
  136.         }catch(Exception e){
  137.             throw new ConnectorException(e.getMessage(),e);
  138.         }
  139.     }
  140.    
  141.     @Override
  142.     public void setThresholdContext(Context context,
  143.             int soglia, File repositoryFile) {
  144.         this.context = context;
  145.         if(this.context!=null) {
  146.             this.idTransazione = (String) this.context.getObject(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE);
  147.         }
  148.         this.soglia = soglia;
  149.         this.repositoryFile = repositoryFile;
  150.        
  151.         if(this._timeoutIS!=null && this.context!=null) {
  152.             this._timeoutIS.updateContext(this.context);
  153.         }
  154.         if(this._limitedIS!=null && this.context!=null) {
  155.             this._limitedIS.updateContext(this.context);
  156.         }
  157.     }
  158.    
  159.     @Override
  160.     public void setRequestReadTimeout(SogliaReadTimeout timeout) {
  161.         this.requestReadTimeout = timeout;
  162.         if(this._timeoutIS!=null) {
  163.             try {
  164.                 this._timeoutIS.updateThreshold(this.requestReadTimeout.getSogliaMs());
  165.             }catch(Exception e) {
  166.                 throw new RuntimeException(e.getMessage(),e); // non dovrebbe mai succedere essendo chiamato il metodo solo se timeout e' maggiore di 0
  167.             }
  168.             TimeoutNotifier notifier = new TimeoutNotifier(this.context, this.getProtocolFactory(),
  169.                     this.requestReadTimeout, TimeoutNotifierType.REQUEST, this.log, true);
  170.             this._timeoutIS.updateNotifier(notifier);
  171.         }
  172.     }
  173.     @Override
  174.     public void disableReadTimeout() {
  175.         if(this._timeoutIS!=null) {
  176.             this._timeoutIS.disableCheckTimeout();
  177.         }
  178.     }
  179.     @Override
  180.     public void setRequestLimitedStream(SogliaDimensioneMessaggio requestLimitSize) {      
  181.         this.requestLimitSize = requestLimitSize;
  182.         if(this._limitedIS!=null && this.requestLimitSize!=null && this.requestLimitSize.getSogliaKb()>0) {
  183.             try {
  184.                 long limitBytes = this.requestLimitSize.getSogliaKb()*1024; // trasformo kb in bytes
  185.                 this._limitedIS.updateThreshold(limitBytes);
  186.             }catch(Exception e) {
  187.                 throw new UtilsRuntimeException(e.getMessage(),e); // non dovrebbe mai succedere essendo chiamato il metodo solo se la soglia e' maggiore di 0
  188.             }
  189.             LimitExceededNotifier notifier = new LimitExceededNotifier(this.context, this.requestLimitSize, this.log);
  190.             this._limitedIS.updateNotifier(notifier);
  191.         }
  192.     }
  193.     @Override
  194.     public void disableLimitedStream() {
  195.         if(this._limitedIS!=null) {
  196.             this._limitedIS.disableCheck();
  197.         }
  198.         this.requestLimitSizeDisabled = true;
  199.     }
  200.     @Override
  201.     public void checkContentLengthLimit() throws LimitExceededIOException {
  202.         // !NOTA!
  203.         // devo comunque verificare l'input stream per evitare che una informazione sbagliata nell'header faccia superare la policy
  204.         // quindi questo controllo non รจ alternativo a quello sullo stream
  205.         if(!this.requestLimitSizeDisabled && this.requestLimitSize!=null && this.requestLimitSize.getSogliaKb()>0 && this.requestLimitSize.isUseContentLengthHeader()) {
  206.             List<String> l = TransportUtils.getHeaderValues(this.req, HttpConstants.CONTENT_LENGTH);
  207.             if(l!=null && !l.isEmpty()) {
  208.                 LimitExceededNotifier notifier = new LimitExceededNotifier(this.context, this.requestLimitSize, this.log);
  209.                 DimensioneMessaggiUtils.verifyByContentLength(this.log, l, this.requestLimitSize, notifier, this.context, DimensioneMessaggiUtils.REQUEST);
  210.             }
  211.         }
  212.     }
  213.     @Override
  214.     public void setDiagnosticProducer(Context context, MsgDiagnostico msgDiag) {
  215.         if(this.context==null) {
  216.             this.context = context;
  217.         }
  218.         this.msgDiagnostico = msgDiag;
  219.     }
  220.     private InputStream buildInputStream() throws IOException {
  221.        
  222.         if(this.buffered) {
  223.             if(this.buffer!=null && this.buffer.size()>0) {
  224.                 return new ByteArrayInputStream(this.buffer.toByteArray());
  225.             }
  226.         }
  227.        
  228.         if(this.is!=null && this.soapReader!=null) {
  229.             return this.is; // stream timeout gia' utilizzato per il soapReader
  230.         }
  231.        
  232.         if(this.is!=null && this.requestLimitSize!=null && this.requestLimitSize.getSogliaKb()>0) {
  233.             LimitExceededNotifier notifier = new LimitExceededNotifier(this.context, this.requestLimitSize, this.log);
  234.             long limitBytes = this.requestLimitSize.getSogliaKb()*1024; // trasformo kb in bytes
  235.             this._limitedIS = new LimitedInputStream(this.is, limitBytes,
  236.                     CostantiPdD.PREFIX_LIMITED_REQUEST,
  237.                     this.context,
  238.                     notifier);
  239.             this.is = this._limitedIS;
  240.         }
  241.         if(this.is!=null && this.requestReadTimeout!=null && this.requestReadTimeout.getSogliaMs()>0) {
  242.             TimeoutNotifier notifier = new TimeoutNotifier(this.context, this.getProtocolFactory(),
  243.                     this.requestReadTimeout, TimeoutNotifierType.REQUEST, this.log, true);
  244.             this._timeoutIS = new TimeoutInputStream(this.is, this.requestReadTimeout.getSogliaMs(),
  245.                     CostantiPdD.PREFIX_TIMEOUT_REQUEST,
  246.                     this.context,
  247.                     notifier);
  248.             this.is = this._timeoutIS;
  249.         }
  250.         if(this.is!=null && this.useDiagnosticInputStream && this.msgDiagnostico!=null) {
  251.             String idModuloFunzionale =
  252.                     IDService.PORTA_APPLICATIVA.equals(this.idModuloAsIDService) ?
  253.                             MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_BUSTE : MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_CONTENUTI_APPLICATIVI;
  254.             this._diagnosticIS = new DiagnosticInputStream(this.is, idModuloFunzionale, "letturaPayloadRichiesta", true, this.msgDiagnostico,
  255.                     (this.log!=null) ? this.log : OpenSPCoop2Logger.getLoggerOpenSPCoopCore(),
  256.                     this.context);
  257.             this.is = this._diagnosticIS;
  258.         }
  259.         return this.is;
  260.     }
  261.    
  262.     @Override
  263.     public IDService getIdModuloAsIDService(){
  264.         return this.idModuloAsIDService;
  265.     }
  266.    
  267.     @Override
  268.     public String getIdModulo(){
  269.         return this.idModulo;
  270.     }
  271.    
  272.     @Override
  273.     public void updateRequestInfo(RequestInfo requestInfo) throws ConnectorException{
  274.         this.requestInfo = requestInfo;
  275.         if(IDService.PORTA_APPLICATIVA.equals(this.idModuloAsIDService)){
  276.             this.requestMessageType = this.getRequestInfo().getProtocolRequestMessageType();
  277.         }
  278.         else{
  279.             this.requestMessageType = this.getRequestInfo().getIntegrationRequestMessageType();
  280.         }
  281.     }
  282.    
  283.     @Override
  284.     public RequestInfo getRequestInfo(){
  285.         return this.requestInfo;
  286.     }
  287.    
  288.     @Override
  289.     public MessageType getRequestMessageType() {
  290.         return this.requestMessageType;
  291.     }
  292.    
  293.     @Override
  294.     public Object getAttribute(String key) throws ConnectorException {
  295.         return this.req.getAttribute(key);
  296.     }
  297.    
  298.     @Override
  299.     public List<String> getHeaderValues(String key) throws ConnectorException{
  300.         return TransportUtils.getHeaderValues(this.req, key);
  301.     }
  302.    
  303.     @Override
  304.     public List<String> getParameterValues(String key) throws ConnectorException{
  305.         return TransportUtils.getParameterValues(this.req, key);
  306.     }

  307.     @Override
  308.     public IProtocolFactory<?> getProtocolFactory() {
  309.         return this.requestInfo.getProtocolFactory();
  310.     }
  311.    
  312.     @Override
  313.     public String getContentType() throws ConnectorException{
  314.         try{
  315.             return this.requestInfo.getProtocolContext().getContentType(true);
  316.         }catch(Exception e){
  317.             throw new ConnectorException(e.getMessage(),e);
  318.         }
  319.     }
  320.    
  321.     @Override
  322.     public String getSOAPAction() throws ConnectorException{
  323.         try{
  324.             String contentType = this.getContentType();
  325.             return SoapUtils.getSoapAction(this.requestInfo.getProtocolContext(), this.requestMessageType, contentType);
  326.         }catch(Exception e){
  327.             throw new ConnectorException(e.getMessage(),e);
  328.         }
  329.     }
  330.    
  331.     @Override
  332.     public OpenSPCoop2MessageSoapStreamReader getSoapReader() throws ConnectorException{
  333.         try{
  334.             if(this.openspcoopProperties.useSoapMessageReader()) {
  335.                 if(this.buffered) {
  336.                     return null; // deve essere chiamato prima
  337.                 }
  338.                
  339.                 if(this.soapReader!=null) {
  340.                     return this.soapReader;
  341.                 }
  342.                
  343.                 String contentType = getContentType();
  344.                 if(contentType!=null) {
  345.                     this.soapReader = new OpenSPCoop2MessageSoapStreamReader(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), contentType,
  346.                             this.buildInputStream(), this.openspcoopProperties.getSoapMessageReaderBufferThresholdKb());
  347.                     try {
  348.                         this.soapReader.read();
  349.                     }finally {
  350.                         // anche in caso di eccezione devo cmq aggiornare is
  351.                         this.is = this.soapReader.getBufferedInputStream();
  352.                     }
  353.                 }
  354.                 return this.soapReader;
  355.             }
  356.             return null;
  357.         }catch(Exception e){
  358.             throw new ConnectorException(e.getMessage(),e);
  359.         }
  360.     }
  361.    
  362.     @Override
  363.     public OpenSPCoop2MessageParseResult getRequest(NotifierInputStreamParams notifierInputStreamParams) throws ConnectorException{
  364.         try{
  365.             OpenSPCoop2MessageParseResult pr = org.openspcoop2.pdd.core.Utilities.getOpenspcoop2MessageFactory(this.log,this.requestInfo, MessageRole.REQUEST).createMessage(this.requestMessageType,
  366.                     this.requestInfo.getProtocolContext(),
  367.                     this.buildInputStream(),notifierInputStreamParams, this.soapReader,
  368.                     this.openspcoopProperties.getAttachmentsProcessingMode());
  369.             this.dataIngressoRichiesta = DateManager.getDate();
  370.             return pr;
  371.         }catch(Exception e){
  372.             throw new ConnectorException(e.getMessage(),e);
  373.         }  
  374.     }

  375.     // Metodo utile per il dump
  376.     public OpenSPCoop2MessageParseResult getRequest(DumpByteArrayOutputStream buffer,NotifierInputStreamParams notifierInputStreamParams) throws ConnectorException{
  377.         try{
  378.             InputStream in = null;
  379.             try{
  380.                 Utilities.writeAsByteArrayOuputStream(buffer, this.buildInputStream(),false); // se l'input stream is empty ritorna null grazie al parametro false
  381.                 if(buffer.size()>0) {
  382.                     if(buffer.isSerializedOnFileSystem()) {
  383.                         in = new FileInputStream(buffer.getSerializedFile());
  384.                     }
  385.                     else {
  386.                         in = new ByteArrayInputStream(buffer.toByteArray());
  387.                     }
  388.                 }
  389.             }catch(Throwable t){
  390.                 OpenSPCoop2MessageParseResult result = new OpenSPCoop2MessageParseResult();
  391.                 result.setParseException(ParseExceptionUtils.buildParseException(t,MessageRole.REQUEST));
  392.                 return result;
  393.             }
  394.             OpenSPCoop2MessageParseResult pr = org.openspcoop2.pdd.core.Utilities.getOpenspcoop2MessageFactory(this.log,this.requestInfo, MessageRole.REQUEST).createMessage(this.requestMessageType,
  395.                     this.requestInfo.getProtocolContext(),
  396.                     in,notifierInputStreamParams,this.soapReader,
  397.                     this.openspcoopProperties.getAttachmentsProcessingMode());
  398.             this.dataIngressoRichiesta = DateManager.getDate();
  399.             return pr;
  400.         }catch(Throwable t){
  401.             //throw new ConnectorException(e.getMessage(),e);
  402.             OpenSPCoop2MessageParseResult result = new OpenSPCoop2MessageParseResult();
  403.             result.setParseException(ParseExceptionUtils.buildParseException(t,MessageRole.REQUEST));
  404.             return result;
  405.         }  
  406.     }

  407.     @Override
  408.     public DumpByteArrayOutputStream getRequest() throws ConnectorException{
  409.         return getRequest(true);
  410.     }
  411.    
  412.     @Override
  413.     public DumpByteArrayOutputStream getRequest(boolean consume) throws ConnectorException{
  414.         if(this.buffered) {
  415.             return this.buffer;
  416.         }
  417.         DumpByteArrayOutputStream bout = null;
  418.         try{
  419.             this.dataIngressoRichiesta = DateManager.getDate();
  420.            
  421.             bout = new DumpByteArrayOutputStream(this.soglia, this.repositoryFile, this.idTransazione,
  422.                     TipoMessaggio.RICHIESTA_INGRESSO_DUMP_BINARIO.getValue());
  423.             Utilities.writeAsByteArrayOuputStream(bout, this.buildInputStream(),false); // se l'input stream is empty ritorna null grazie al parametro false
  424.             bout.flush();
  425.             return bout;
  426.         }catch(Exception e){
  427.             throw new ConnectorException(e.getMessage(),e);
  428.         }finally {
  429.             try {
  430.                 if(bout!=null) {
  431.                     bout.close();
  432.                 }
  433.             }catch(Throwable t) {
  434.                 // ignore
  435.             }
  436.             if(!consume) {
  437.                 this.buffer = bout;
  438.                 this.buffered = true;
  439.             }
  440.         }
  441.     }
  442.    
  443.     @Override
  444.     public Date getDataIngressoRichiesta(){
  445.         return this.dataIngressoRichiesta;
  446.     }
  447.    
  448.     @Override
  449.     public URLProtocolContext getURLProtocolContext() throws ConnectorException{
  450.         try{
  451.             return this.requestInfo.getProtocolContext();
  452.         }catch(Exception e){
  453.             throw new ConnectorException(e.getMessage(),e);
  454.         }
  455.     }
  456.    
  457.     @Override
  458.     public Credential getCredential() throws ConnectorException{
  459.         try{
  460.             return this.requestInfo.getProtocolContext().getCredential();
  461.         }catch(Exception e){
  462.             throw new ConnectorException(e.getMessage(),e);
  463.         }  
  464.     }
  465.    
  466.     @Override
  467.     public String getSource() throws ConnectorException{
  468.         try{
  469.              return this.requestInfo.getProtocolContext().getSource();
  470.         }catch(Exception e){
  471.             throw new ConnectorException(e.getMessage(),e);
  472.         }  
  473.     }
  474.    
  475.     @Override
  476.     public String getProtocol() throws ConnectorException{
  477.         return this.req.getProtocol();
  478.     }
  479.    
  480.     @Override
  481.     public int getContentLength() throws ConnectorException{
  482.         return this.req.getContentLength();
  483.     }
  484.    
  485.     @Override
  486.     public void close() throws ConnectorException{
  487.         try{
  488.             if(this.is!=null){
  489.                 try{
  490.                     this.is.close();
  491.                     this.is = null;
  492.                 }catch(Exception e){}
  493.             }
  494.         }catch(Exception e){
  495.             throw new ConnectorException(e.getMessage(),e);
  496.         }  
  497.     }
  498.    
  499.     @Override
  500.     public String getRemoteAddress() throws ConnectorException{
  501.         return this.req.getRemoteAddr();
  502.     }
  503.    
  504.     public HttpServletRequest getHttpServletRequest(){
  505.         return this.req;
  506.     }
  507. }