DumpRawConnectorOutMessage.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.pdd.services.connector.messages;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
import org.openspcoop2.message.OpenSPCoop2Message;
import org.openspcoop2.message.OpenSPCoop2MessageProperties;
import org.openspcoop2.message.OpenSPCoop2RestMessage;
import org.openspcoop2.message.OpenSPCoop2SoapMessage;
import org.openspcoop2.message.constants.MessageRole;
import org.openspcoop2.message.constants.MessageType;
import org.openspcoop2.message.constants.ServiceBinding;
import org.openspcoop2.message.exception.ParseException;
import org.openspcoop2.message.exception.ParseExceptionUtils;
import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
import org.openspcoop2.pdd.services.DumpRaw;
import org.openspcoop2.pdd.services.connector.ConnectorException;
import org.openspcoop2.protocol.sdk.Context;
import org.openspcoop2.utils.io.DumpByteArrayOutputStream;
import org.openspcoop2.utils.transport.TransportUtils;
import org.slf4j.Logger;
/**
* DumpRawConnectorOutMessage
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class DumpRawConnectorOutMessage implements ConnectorOutMessage {
private Logger log;
private ConnectorOutMessage connectorOutMessage;
private DumpByteArrayOutputStream bout = null;
private MessageType messageType = null;
private ParseException parseException = null;
private Map<String, List<String>> trasporto = new HashMap<>();
private Integer contentLenght;
private String contentType;
private Integer status;
private OpenSPCoop2Properties openspcoopProperties;
private Context context;
private String idTransazione;
private int soglia;
private File repositoryFile;
private DumpRaw dumpRaw;
public DumpRawConnectorOutMessage(Logger log,ConnectorOutMessage connectorOutMessage, Context context,
int soglia, File repositoryFile,
DumpRaw dump){
this.log = log;
this.connectorOutMessage = connectorOutMessage;
this.openspcoopProperties = OpenSPCoop2Properties.getInstance();
this.context = context;
if(this.context!=null) {
this.idTransazione = (String) this.context.getObject(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE);
}
this.soglia = soglia;
this.repositoryFile = repositoryFile;
this.dumpRaw = dump;
}
public ConnectorOutMessage getWrappedConnectorOutMessage() {
return this.connectorOutMessage;
}
public DumpByteArrayOutputStream getDumpByteArrayOutputStream() {
if(this.bout!=null && this.bout.size()>0){
return this.bout;
}
return null;
}
// public byte[] getResponseAsByte(){
// if(this.bout!=null && this.bout.size()>0){
// return this.bout.toByteArray();
// }
// return null;
// }
// public String getResponseAsString(){
// if(this.bout!=null && this.bout.size()>0){
// return this.bout.toString();
// }
// return null;
// }
public MessageType getMessageType() {
return this.messageType;
}
public boolean isParsingResponseError(){
return this.parseException!=null;
}
public String getParsingResponseErrorAsString(){
if(this.parseException!=null){
try{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(bout);
this.parseException.getSourceException().printStackTrace(pw);
pw.flush();
bout.flush();
pw.close();
bout.close();
return bout.toString();
}catch(Exception e){
return "ParsingResponseError, serializazione eccezione non riuscita: "+e.getMessage();
}
}
return null;
}
public Map<String, List<String>> getTrasporto() {
return this.trasporto;
}
public Integer getContentLenght() {
return this.contentLenght;
}
public String getContentType() {
return this.contentType;
}
public Integer getStatus() {
return this.status;
}
private boolean emitDiagnostic = false;
private void emitDiagnosticStartDumpBinarioRispostaUscita() {
if(this.dumpRaw!=null && !this.emitDiagnostic) {
this.emitDiagnostic = true;
this.dumpRaw.emitDiagnosticStartDumpBinarioRispostaUscita();
}
}
private void _sendHeaders(OpenSPCoop2Message message) throws Exception {
if(message==null) {
throw new Exception("Message is null");
}
// Eventuali header http propagati
OpenSPCoop2MessageProperties forwardHeader = null;
if(ServiceBinding.REST.equals(message.getServiceBinding())) {
forwardHeader = message.getForwardTransportHeader(this.openspcoopProperties.getRESTServicesHeadersForwardConfig(false));
}
else {
forwardHeader = message.getForwardTransportHeader(this.openspcoopProperties.getSOAPServicesHeadersForwardConfig(false));
}
if(forwardHeader!=null && forwardHeader.size()>0){
Iterator<String> keys = forwardHeader.getKeys();
while (keys.hasNext()) {
String key = (String) keys.next();
List<String> values = forwardHeader.getPropertyValues(key);
if(values!=null && !values.isEmpty()) {
for (String value : values) {
this.addHeader(key, value);
}
}
}
}
}
@Override
public void sendResponse(OpenSPCoop2Message message, boolean consume)
throws ConnectorException {
emitDiagnosticStartDumpBinarioRispostaUscita();
try{
// Propago eventuali header http
this._sendHeaders(message);
// Prima lo registro e dopo serializzo
if(this.bout!=null){
this.bout.clearResources();
this.bout = null;
}
this.bout = new DumpByteArrayOutputStream(this.soglia, this.repositoryFile, this.idTransazione,
TipoMessaggio.RISPOSTA_USCITA_DUMP_BINARIO.getValue());
boolean hasContent = false;
// il save e' necessario con i connettori in caso di errori di validazione
if(message!=null && ServiceBinding.SOAP.equals(message.getServiceBinding())){
hasContent = true;
OpenSPCoop2SoapMessage soap = message.castAsSoap();
if(soap.hasSOAPFault()){
soap.saveChanges();
}
}
if(message!=null && ServiceBinding.REST.equals(message.getServiceBinding())){
OpenSPCoop2RestMessage<?> rest = message.castAsRest();
hasContent = rest.hasContent();
}
if(hasContent) {
message.writeTo(this.bout, consume);
}
if(message!=null) {
this.messageType = message.getMessageType();
}
}catch(Throwable t){
this.bout = null;
if(message.getParseException()!=null){
this.parseException = message.getParseException();
}
else{
this.parseException = ParseExceptionUtils.buildParseException(t,MessageRole.RESPONSE);
}
this.log.error("SendResponse error: "+t.getMessage(),t);
// Devo lanciare l'eccezione senno il servizio esce con 200
throw new ConnectorException(this.parseException.getSourceException());
}finally{
try{
if(this.bout!=null){
this.bout.flush();
}
}catch(Throwable close){}
try{
if(this.bout!=null){
this.bout.close();
}
}catch(Throwable close){}
}
// wrapped method
//this.connectorOutMessage.sendResponse(message, consume); Nel caso di attachments genera un nuovo boundary
if(this.bout!=null){
this.connectorOutMessage.sendResponse(this.bout);
}
}
@Override
public void sendResponse(DumpByteArrayOutputStream message) throws ConnectorException {
emitDiagnosticStartDumpBinarioRispostaUscita();
try{
// Prima lo registro e dopo serializzo
if(this.bout!=null){
this.bout.clearResources();
this.bout = null;
}
if(message!=null && message.size()>0) {
this.bout = message;
}
}catch(Throwable t){
try{
this.bout = DumpByteArrayOutputStream.newInstance(("SendResponse byte[] error: "+t.getMessage()).getBytes());
}catch(Throwable tWrite){}
this.log.error("SendResponse byte[] error: "+t.getMessage(),t);
}finally{
try{
if(this.bout!=null){
this.bout.flush();
}
}catch(Throwable close){}
try{
if(this.bout!=null){
this.bout.close();
}
}catch(Throwable close){}
}
// wrapped method
this.connectorOutMessage.sendResponse(message);
}
@Override
public void sendResponseHeaders(OpenSPCoop2Message message) throws ConnectorException{
emitDiagnosticStartDumpBinarioRispostaUscita();
try{
// Propago eventuali header http
this._sendHeaders(message);
}catch(Exception e){
throw new ConnectorException(e.getMessage(),e);
}
}
@Override
public void setHeader(String key, String value) throws ConnectorException {
try{
// Prima lo registro e dopo serializzo
TransportUtils.setHeader(this.trasporto, key, value);
}catch(Throwable t){
try{
this.bout = DumpByteArrayOutputStream.newInstance(("setHeader ["+key+"] error: "+t.getMessage()).getBytes());
}catch(Throwable tWrite){}
this.log.error("Set Header ["+key+"]["+value+"] error: "+t.getMessage(),t);
}
// wrapped method
this.connectorOutMessage.setHeader(key,value);
}
@Override
public void addHeader(String key, String value) throws ConnectorException {
try{
// Prima lo registro e dopo serializzo
TransportUtils.addHeader(this.trasporto, key, value);
}catch(Throwable t){
try{
this.bout = DumpByteArrayOutputStream.newInstance(("addHeader ["+key+"] error: "+t.getMessage()).getBytes());
}catch(Throwable tWrite){}
this.log.error("Add Header ["+key+"]["+value+"] error: "+t.getMessage(),t);
}
// wrapped method
this.connectorOutMessage.addHeader(key,value);
}
@Override
public void setContentLength(int length) throws ConnectorException {
// Prima lo registro
this.contentLenght = length;
// wrapped method
this.connectorOutMessage.setContentLength(length);
}
@Override
public void setContentType(String type) throws ConnectorException {
// Prima lo registro
this.contentType = type;
// wrapped method
this.connectorOutMessage.setContentType(type);
}
@Override
public void setStatus(int status) throws ConnectorException {
// Prima lo registro
this.status = status;
// wrapped method
this.connectorOutMessage.setStatus(status);
}
// Wrapped Only
@Override
public int getResponseStatus() throws ConnectorException {
// wrapped method
return this.connectorOutMessage.getResponseStatus();
}
@Override
public void flush(boolean throwException) throws ConnectorException {
// wrapped method
this.connectorOutMessage.flush(throwException);
}
@Override
public void close(boolean throwException) throws ConnectorException {
// wrapped method
this.connectorOutMessage.close(throwException);
}
}