DumpRestMessageUtils.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.message.rest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.mail.BodyPart;
import org.openspcoop2.message.OpenSPCoop2RestMessage;
import org.openspcoop2.message.OpenSPCoop2RestMimeMultipartMessage;
import org.openspcoop2.message.constants.MessageType;
import org.openspcoop2.message.exception.MessageException;
import org.openspcoop2.message.utils.DumpAttachment;
import org.openspcoop2.message.utils.DumpMessaggio;
import org.openspcoop2.message.utils.DumpMessaggioConfig;
import org.openspcoop2.message.utils.DumpMessaggioMultipartInfo;
import org.openspcoop2.utils.dch.MailcapActivationReader;
import org.openspcoop2.utils.mime.MimeMultipart;
import org.openspcoop2.utils.transport.http.HttpConstants;
/**
* DumpRestMessageUtils
*
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class DumpRestMessageUtils {
public static DumpMessaggio dumpMessage(OpenSPCoop2RestMessage<?> msg, boolean dumpAllBodyParts) throws MessageException{
return dumpMessage(msg, new DumpMessaggioConfig(), dumpAllBodyParts);
}
@SuppressWarnings("incomplete-switch")
public static DumpMessaggio dumpMessage(OpenSPCoop2RestMessage<?> msg,
DumpMessaggioConfig config,
boolean dumpAllBodyParts) throws MessageException{
try{
DumpMessaggio dumpMessaggio = new DumpMessaggio();
dumpMessaggio.setMessageType(msg.getMessageType());
Map<String, List<String>> pTrasporto = null;
if(msg.getTransportRequestContext()!=null) {
if(msg.getTransportRequestContext().getHeaders()!=null &&
msg.getTransportRequestContext().getHeaders().size()>0){
if(config.isDumpHeaders()) {
pTrasporto = msg.getTransportRequestContext().getHeaders();
}
}
}
else if(msg.getTransportResponseContext()!=null) {
if(msg.getTransportResponseContext().getHeaders()!=null &&
msg.getTransportResponseContext().getHeaders().size()>0){
if(config.isDumpHeaders()) {
pTrasporto = msg.getTransportResponseContext().getHeaders();
}
}
}
if(config.isDumpHeaders() && pTrasporto!=null) {
Iterator<String> keys = pTrasporto.keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
if(key!=null){
List<String> values = pTrasporto.get(key);
dumpMessaggio.getHeadersValues().put(key, values);
}
}
}
boolean hasContent = msg.hasContent();
if(hasContent){
dumpMessaggio.setContentType(msg.getContentType());
// La registrazione su log dello stream completo non e' una funzionalita' simmetrica rispetto al dump fatto su soap
if(config.isDumpBody()) {
if(!MessageType.MIME_MULTIPART.equals(msg.getMessageType())) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
switch (msg.getMessageType()) {
case XML:
bout.write(msg.castAsRestXml().getContentAsByteArray());
break;
case JSON:
bout.write(msg.castAsRestJson().getContentAsByteArray());
break;
case BINARY:
bout.write(msg.castAsRestBinary().getContent().getContent());
break;
default:
throw new MessageException("MessageType ["+msg.getMessageType()+"] unsupported");
}
bout.flush();
bout.close();
dumpMessaggio.setBody(bout);
}
}
}
if((config.isDumpBody() || config.isDumpAttachments()) && hasContent &&
MessageType.MIME_MULTIPART.equals(msg.getMessageType())){
OpenSPCoop2RestMimeMultipartMessage msgMime = msg.castAsRestMimeMultipart();
MultipartContent mc = msgMime.getContent();
MimeMultipart mimeMultipart = (mc!=null) ? mc.getMimeMultipart() : null;
if(mimeMultipart!=null) {
for (int i = 0; i < mimeMultipart.countBodyParts(); i++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
if(i>0) {
if(!config.isDumpAttachments()) {
break;
}
}
DumpMessaggioMultipartInfo multipartInfoBody = null;
DumpAttachment dumpAttach = null;
if(i==0 && config.isDumpBody()) {
multipartInfoBody = new DumpMessaggioMultipartInfo();
multipartInfoBody.setContentId(mimeMultipart.getContentID(bodyPart));
multipartInfoBody.setContentLocation(mimeMultipart.getContentDisposition(bodyPart)); // Uso Disposition in REST, più opportuna
multipartInfoBody.setContentType(bodyPart.getContentType());
}
else {
dumpAttach = new DumpAttachment();
dumpAttach.setContentId(mimeMultipart.getContentID(bodyPart));
dumpAttach.setContentLocation(mimeMultipart.getContentDisposition(bodyPart)); // Uso Disposition in REST, più opportuna
dumpAttach.setContentType(bodyPart.getContentType());
}
if(config.isDumpMultipartHeaders()) {
Enumeration<?> en = bodyPart.getAllHeaders();
if(en!=null) {
while(en.hasMoreElements()) {
Object keyO = en.nextElement();
if(keyO instanceof String) {
String key = (String) keyO;
String [] values = bodyPart.getHeader(key);
List<String> lValues = new ArrayList<>();
if(values!=null && values.length>0) {
for (int j = 0; j < values.length; j++) {
lValues.add(values[j]);
}
}
if(!lValues.isEmpty()) {
if(multipartInfoBody!=null) {
multipartInfoBody.getHeadersValues().put(key, lValues);
}
else {
dumpAttach.getHeadersValues().put(key, lValues);
}
}
}
else if(keyO instanceof javax.mail.Header) {
javax.mail.Header hdr = (javax.mail.Header) keyO;
if(hdr!=null && hdr.getName()!=null) {
if(multipartInfoBody!=null) {
List<String> lValues = null;
if(multipartInfoBody.getHeadersValues().containsKey(hdr.getName())) {
lValues = multipartInfoBody.getHeadersValues().get(hdr.getName());
}
else {
lValues = new ArrayList<>();
multipartInfoBody.getHeadersValues().put(hdr.getName(), lValues);
}
lValues.add(hdr.getValue());
}
else {
List<String> lValues = null;
if(dumpAttach.getHeadersValues().containsKey(hdr.getName())) {
lValues = dumpAttach.getHeadersValues().get(hdr.getName());
}
else {
lValues = new ArrayList<>();
dumpAttach.getHeadersValues().put(hdr.getName(), lValues);
}
lValues.add(hdr.getValue());
}
}
}
}
}
}
ByteArrayOutputStream boutAttach = null;
if(dumpAllBodyParts){
boutAttach = (ByteArrayOutputStream) DumpRestMessageUtils._dumpBodyPart(msg, bodyPart, true);
}else{
Object o = _dumpBodyPart(msg, bodyPart, false);
if(o == null){
dumpAttach.setErrorContentNotSerializable("Contenuto attachment non recuperato??");
}
else if(o instanceof String){
boutAttach = new ByteArrayOutputStream();
boutAttach.write(((String)o).getBytes());
boutAttach.flush();
boutAttach.close();
}
else if(o instanceof java.io.ByteArrayOutputStream){
boutAttach = (java.io.ByteArrayOutputStream) o;
}
else{
dumpAttach.setErrorContentNotSerializable("Contenuto attachment non è visualizzabile, tipo: "+o.getClass().getName());
}
}
if(multipartInfoBody!=null) {
dumpMessaggio.setBody(boutAttach);
dumpMessaggio.setMultipartInfoBody(multipartInfoBody);
}
else {
dumpAttach.setContent(boutAttach);
if(dumpMessaggio.getAttachments()==null) {
dumpMessaggio.setAttachments(new ArrayList<>());
}
dumpMessaggio.getAttachments().add(dumpAttach);
}
}
}
}
return dumpMessaggio;
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
public static String dumpMessageAsString(DumpMessaggio msg, boolean dumpAllAttachments) throws MessageException{
return dumpMessageAsString(msg, new DumpMessaggioConfig(), dumpAllAttachments);
}
public static String dumpMessageAsString(DumpMessaggio msg,
DumpMessaggioConfig config, boolean dumpAllAttachments) throws MessageException{
try{
StringBuilder out = new StringBuilder(msg.toString(config,dumpAllAttachments));
return out.toString();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
public static String dumpMessageAsString(OpenSPCoop2RestMessage<?> msg,
boolean dumpAllBodyParts) throws MessageException{
return dumpMessageAsString(msg, new DumpMessaggioConfig(), dumpAllBodyParts);
}
public static String dumpMessageAsString(OpenSPCoop2RestMessage<?> msg,
DumpMessaggioConfig config,
boolean dumpAllBodyParts) throws MessageException{
try{
StringBuilder out = new StringBuilder();
Map<String,List<String>> pTrasporto = null;
if(msg.getTransportRequestContext()!=null) {
if(msg.getTransportRequestContext().getHeaders()!=null &&
msg.getTransportRequestContext().getHeaders().size()>0){
if(config.isDumpHeaders()) {
pTrasporto = msg.getTransportRequestContext().getHeaders();
}
}
}
else if(msg.getTransportResponseContext()!=null) {
if(msg.getTransportResponseContext().getHeaders()!=null &&
msg.getTransportResponseContext().getHeaders().size()>0){
if(config.isDumpHeaders()) {
pTrasporto = msg.getTransportResponseContext().getHeaders();
}
}
}
if(config.isDumpHeaders()) {
out.append("------ Header di trasporto ------\n");
if(pTrasporto!=null && pTrasporto.size()>0) {
Iterator<String> keys = pTrasporto.keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
if(key!=null){
List<String> values = pTrasporto.get(key);
if(values!=null && !values.isEmpty()) {
for (String value : values) {
out.append("- "+key+": "+value+"\n");
}
}
}
}
}
else {
out.append("Non presenti\n");
}
}
boolean hasContent = msg.hasContent();
String contentString = "Body";
String contentType = "";
if(!hasContent){
contentString = "Empty Body";
}
if(hasContent) {
if(msg.getContentType()!=null) {
contentType = " (ContentType: "+msg.getContentType()+")";
}
}
if(config.isDumpBody()) {
out.append("------ "+contentString+contentType+" ("+msg.getMessageType()+") ------\n");
// Nel caso di multipart non il body e gli attachments devono essere gestiti nell'iterazione successiva
// Se si usa il metodo 'msg.getContentAsString()' si ottiene lo stream completo
if(!MessageType.MIME_MULTIPART.equals(msg.getMessageType())) {
out.append("\n");
if(hasContent) {
out.append(msg.getContentAsString());
}
}
}
if((config.isDumpBody() || config.isDumpAttachments()) && hasContent && MessageType.MIME_MULTIPART.equals(msg.getMessageType())){
OpenSPCoop2RestMimeMultipartMessage msgMime = msg.castAsRestMimeMultipart();
MultipartContent mc = msgMime.getContent();
MimeMultipart mimeMultipart = mc!=null ? mc.getMimeMultipart() : null;
if(mimeMultipart!=null) {
for (int i = 0; i < mimeMultipart.countBodyParts(); i++) {
if(i>0) {
if(!config.isDumpAttachments()) {
break;
}
}
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
if(i>0 || !config.isDumpBody()) {
out.append("\n------ BodyPart-"+(i+1)+" ------\n");
}
out.append("\n*** MimePart Header ***\n");
String contentIdBodyPart = mimeMultipart.getContentID(bodyPart);
if(contentIdBodyPart!=null) {
out.append("- "+HttpConstants.CONTENT_ID+": "+contentIdBodyPart+"\n");
}
String contentLocationBodyPart = mimeMultipart.getContentDisposition(bodyPart); // Uso Disposition in REST, più opportuna
if(contentLocationBodyPart!=null) {
out.append("- "+HttpConstants.CONTENT_DISPOSITION+": "+contentLocationBodyPart+"\n");
}
if(bodyPart.getContentType()!=null) {
out.append("- "+HttpConstants.CONTENT_TYPE+": "+bodyPart.getContentType()+"\n");
}
if(config.isDumpMultipartHeaders()) {
Enumeration<?> en = bodyPart.getAllHeaders();
if(en!=null) {
while(en.hasMoreElements()) {
Object keyO = en.nextElement();
if(keyO instanceof String) {
String key = (String) keyO;
if(HttpConstants.CONTENT_ID.equalsIgnoreCase(key) ||
HttpConstants.CONTENT_DISPOSITION.equalsIgnoreCase(key) ||
HttpConstants.CONTENT_TYPE.equalsIgnoreCase(key)) {
continue;
}
String [] values = bodyPart.getHeader(key);
if(values!=null && values.length>0) {
for (int j = 0; j < values.length; j++) {
out.append("- "+key+": "+values[j]+"\n");
}
}
}
}
}
}
out.append("\n");
if(dumpAllBodyParts){
out.append(DumpRestMessageUtils.dumpBodyPart(msg, bodyPart));
}else{
//Object o = ap.getContent(); NON FUNZIONA CON TOMCAT
Object o = bodyPart.getDataHandler().getContent();
//System.out.println("["+o.getClass().getName()+"])"+ap.getContentType()+"(");
if(o instanceof String){
out.append((String)o);
}else{
out.append("Contenuto attachments non è visualizzabile, tipo: "+o.getClass().getName());
}
}
}
}
}
return out.toString();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
public static String dumpBodyPart(OpenSPCoop2RestMessage<?> msg,BodyPart bodyPart) throws MessageException{
Object o = _dumpBodyPart(msg, bodyPart, false);
// Metodo sopra non torna mai null, segnalato da sonarqube
/*if(o == null){
throw new MessageException("Dump error (return null reference)");
}*/
if(o instanceof String){
return (String) o;
}
else if(o instanceof java.io.ByteArrayOutputStream){
java.io.ByteArrayOutputStream bout = null;
try{
bout = (java.io.ByteArrayOutputStream) o;
return bout.toString();
}finally{
try{
if(bout!=null){
bout.close();
}
}catch(Exception eClose){
// close
}
}
}
else{
throw new MessageException("Dump error (return type "+o.getClass().getName()+" unknown)");
}
}
public static byte[] dumpBodyPartAsByteArray(OpenSPCoop2RestMessage<?> msg,BodyPart bodyPart) throws MessageException{
Object o = _dumpBodyPart(msg, bodyPart, false);
// Metodo sopra non torna mai null, segnalato da sonarqube
/*if(o == null){
throw new MessageException("Dump error (return null reference)");
}*/
if(o instanceof String){
return ((String) o).getBytes();
}
else if(o instanceof java.io.ByteArrayOutputStream){
java.io.ByteArrayOutputStream bout = null;
try{
bout = (java.io.ByteArrayOutputStream) o;
return bout.toByteArray();
}finally{
try{
if(bout!=null){
bout.close();
}
}catch(Exception eClose){
// close
}
}
}
else{
throw new MessageException("Dump error (return type "+o.getClass().getName()+" unknown)");
}
}
private static boolean convert = false;
public static void setConvert(boolean convert) {
DumpRestMessageUtils.convert = convert;
}
private static Object _dumpBodyPart(OpenSPCoop2RestMessage<?> msg,BodyPart bodyPart, boolean forceReturnAsByteArrayOutputStream) throws MessageException{
try{
java.io.ByteArrayOutputStream bout = null;
//Object o = ap.getContent(); NON FUNZIONA CON TOMCAT
//java.io.InputStream inputDH = dh.getInputStream(); NON FUNZIONA CON JBOSS7 e JAVA7 e imbustamentoSOAP con GestioneManifest e rootElementMaggioreUno (tipo: application/octet-stream)
Object o = bodyPart.getDataHandler().getContent();
String s = null;
if(o!=null){
if(o instanceof byte[]){
byte[] b = (byte[]) o;
bout = new ByteArrayOutputStream();
bout.write(b);
bout.flush();
bout.close();
}
else if(o instanceof InputStream){
InputStream is = (InputStream) o;
bout = new java.io.ByteArrayOutputStream();
byte [] readB = new byte[8192];
int readByte = 0;
while((readByte = is.read(readB))!= -1)
bout.write(readB,0,readByte);
is.close();
bout.flush();
bout.close();
}
else if(o instanceof String){
s = (String) o;
bout = new ByteArrayOutputStream();
bout.write(s.getBytes());
bout.flush();
bout.close();
}
else{
// Provo con codiceOriginale ma in jboss non funziona sempre
javax.activation.DataHandler dh= bodyPart.getDataHandler();
java.io.InputStream inputDH = dh.getInputStream();
bout = new java.io.ByteArrayOutputStream();
byte [] readB = new byte[8192];
int readByte = 0;
while((readByte = inputDH.read(readB))!= -1)
bout.write(readB,0,readByte);
inputDH.close();
bout.flush();
bout.close();
}
}
else{
// Provo con codiceOriginale ma in jboss non funziona sempre
javax.activation.DataHandler dh= bodyPart.getDataHandler();
java.io.InputStream inputDH = dh.getInputStream();
bout = new java.io.ByteArrayOutputStream();
byte [] readB = new byte[8192];
int readByte = 0;
while((readByte = inputDH.read(readB))!= -1)
bout.write(readB,0,readByte);
inputDH.close();
bout.flush();
bout.close();
}
// Per non perdere quanto letto
// in rest con le api utilizzate non sembra necessario ricostruirlo come si fa in soap.
// anche il caso del tunnel soap non esiste.
if(convert && MailcapActivationReader.existsDataContentHandler(bodyPart.getContentType())){
if(bodyPart.getContentType()!=null && bodyPart.getContentType().startsWith(HttpConstants.CONTENT_TYPE_PLAIN)){
processContentTypeTextPlain(s, bodyPart, bout);
}
else{
//bodyPart.setDataHandler(new javax.activation.DataHandler(bout.toByteArray(),bodyPart.getContentType()));
// Nel caso sia xml si ottiene il seguente errore:
//Invalid Object type = class [B. XmlDCH can only convert DataSource or Source to XML.
// Si potrebbe vederlo di gestire come e' stato fatto per il rebuild dell'attachment su SOAP.
}
}
if(s!=null){
if(forceReturnAsByteArrayOutputStream) {
return bout;
}
else {
return s;
}
}else{
return bout;
}
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
private static void processContentTypeTextPlain(String s, BodyPart bodyPart, java.io.ByteArrayOutputStream bout) throws Exception {
// Se siamo in text plain non devo fare nulla. Comunque non l'ho perso.
// Se uso il codice sotto, poi si perde il content-type, non viene serializzato
/*
if(s!=null){
bodyPart.setDataHandler(new javax.activation.DataHandler(s,bodyPart.getContentType()));
//bodyPart.setContent(s,bodyPart.getContentType());
//bodyPart.setText(s);
}
else{
//bodyPart.setDataHandler(new javax.activation.DataHandler(bout.toByteArray(),bodyPart.getContentType()));
// devo comunque impostare una stringa nel caso di text/plain, senno ottengo un errore:
// "text/plain" DataContentHandler requires String object, was given object of type class [B
bodyPart.setDataHandler(new javax.activation.DataHandler(bout.toString(),bodyPart.getContentType()));
//bodyPart.setContent(bout.toString(),bodyPart.getContentType());
//bodyPart.setText(bout.toString());
}*/
}
}