OpenSPCoop2MessageSoapStreamReader.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.message.soap.reader;

  21. import java.io.ByteArrayInputStream;
  22. import java.io.ByteArrayOutputStream;
  23. import java.io.InputStream;
  24. import java.io.OutputStream;
  25. import java.io.SequenceInputStream;

  26. import javax.xml.parsers.SAXParser;
  27. import javax.xml.parsers.SAXParserFactory;
  28. import javax.xml.soap.MimeHeaders;
  29. import javax.xml.soap.SOAPBody;
  30. import javax.xml.soap.SOAPHeader;

  31. import org.apache.commons.lang.StringUtils;
  32. import org.openspcoop2.message.OpenSPCoop2Message;
  33. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  34. import org.openspcoop2.message.constants.Costanti;
  35. import org.openspcoop2.message.constants.MessageType;
  36. import org.openspcoop2.message.exception.MessageException;
  37. import org.openspcoop2.message.soap.OpenSPCoop2Message_saaj_11_impl;
  38. import org.openspcoop2.message.soap.OpenSPCoop2Message_saaj_12_impl;
  39. import org.openspcoop2.message.soap.SoapUtils;
  40. import org.openspcoop2.utils.Utilities;
  41. import org.openspcoop2.utils.resources.Charset;
  42. import org.openspcoop2.utils.transport.http.ContentTypeUtilities;
  43. import org.openspcoop2.utils.transport.http.HttpConstants;
  44. import org.openspcoop2.utils.xml.TransformerConfig;
  45. import org.openspcoop2.utils.xml.XMLUtils;
  46. import org.w3c.dom.Node;
  47. import org.xml.sax.InputSource;
  48. import org.xml.sax.XMLReader;

  49. /**
  50.  * OpenSPCoop2MessageSoapParser
  51.  *
  52.  * @author Andrea Poli (poli@link.it)
  53.  * @author $Author$
  54.  * @version $Rev$, $Date$
  55.  */
  56. public class OpenSPCoop2MessageSoapStreamReader {

  57.     public static boolean SOAP_HEADER_OPTIMIZATION_ENABLED = true;
  58.    
  59.     @SuppressWarnings("unused")
  60.     private OpenSPCoop2MessageFactory msgFactory;
  61.     private InputStream is;
  62.     private String contentType;
  63.     private int bufferThresholdKb;
  64.    
  65.     public OpenSPCoop2MessageSoapStreamReader(OpenSPCoop2MessageFactory msgFactory, String contentType, InputStream is, int bufferThresholdKb) {
  66.         this.msgFactory = msgFactory;
  67.         this.contentType = contentType;
  68.         this.is = is;
  69.         this.bufferThresholdKb = bufferThresholdKb;
  70.     }

  71.     private String envelope;
  72.     private String prefixEnvelope = null;
  73.     private String namespace;
  74.    
  75.     private String header;
  76.     private String prefixHeader = null;
  77.     private OpenSPCoop2Message _headerMsgCompleto;
  78.     private boolean soapHeaderModified = false;
  79.    
  80.     private boolean soapHeaderOptimizable = false;
  81.     private long startHeaderOffset;
  82.     private long endHeaderOffset;
  83.     private long startBodyOffset;
  84.     private String isCharset;
  85.    
  86.     private String body;
  87.     private boolean bodyEmpty;
  88.     //private Element rootElement;
  89.     private String rootElementNamespace;
  90.     private String rootElementLocalName;
  91.     private String rootElementPrefix;
  92.     private String fault;
  93.    
  94.     private int bufferSize;
  95.    
  96.     private boolean parsingComplete = false;
  97.    
  98.     private MessageException tBuffered = null;
  99.    
  100.     public void checkException() throws MessageException {
  101.         if(this.tBuffered!=null) {
  102.             throw this.tBuffered;
  103.         }
  104.     }
  105.     private InputStream bufferedInputStream = null;
  106.     public InputStream getBufferedInputStream() {
  107.         return this.bufferedInputStream;
  108.     }
  109.     public void releaseBufferedInputStream() {
  110.         this.bufferedInputStream = null;
  111.     }
  112.     public void read() throws MessageException {

  113.         this.bufferedInputStream = this.is;
  114.                
  115.         if(this.tBuffered!=null) {
  116.             throw this.tBuffered;
  117.         }
  118.        
  119.         if(this.contentType==null || StringUtils.isEmpty(this.contentType) || this.is == null) {
  120.             return;
  121.         }
  122.         boolean multipart = false;
  123.         try {
  124.             multipart = ContentTypeUtilities.isMultipartType(this.contentType);
  125.         }catch(Throwable t) {}
  126.         String charset = null;
  127.         try {
  128.             if(!multipart) {
  129.                 charset = ContentTypeUtilities.readCharsetFromContentType(this.contentType);
  130.                 this.isCharset = charset;
  131.                 if(Charset.UTF_8.getValue().equalsIgnoreCase(charset)) {
  132.                     charset = null;
  133.                 }
  134.             }
  135.             else {
  136.                 String internalCT = ContentTypeUtilities.getInternalMultipartContentType(this.contentType);
  137.                 this.isCharset = ContentTypeUtilities.readCharsetFromContentType(internalCT);
  138.             }
  139.         }catch(Throwable t) {}
  140.        
  141.         try {
  142.             ByteArrayOutputStream bufferReaded = new ByteArrayOutputStream();
  143.             int lettiBuffer = 0;
  144.            
  145.             StringBuilder sbActual = null;
  146.             long sbActualOffsetStart = -1;
  147.             byte[] bufferRaw = new byte[1024];
  148.             long bLetti = 0;
  149.             int letturaPrecedente = 0;
  150.             int kbLetti = 0;
  151.            
  152.             boolean envelopeFound = false;
  153.            
  154.             StringBuilder headerBuilder = null;
  155.             String headerClosure = null;
  156.             boolean headerCompletato = false;
  157.            
  158.             boolean bodyFound = false;
  159.             String prefixBody = null;
  160.            
  161.             StringBuilder elementAfterBodyBuilder = null;
  162.            
  163.             boolean cdataFound = false;
  164.             boolean commentFound = false;
  165.            
  166.             boolean analisiTerminata = false;
  167.            
  168. //          String check = org.openspcoop2.utils.Utilities.getAsString(this.is, "UTF8");
  169. //          System.out.println("STREAM: "+check);
  170. //          this.is = new java.io.ByteArrayInputStream(check.getBytes());
  171.            
  172.             while ( (lettiBuffer=this.is.read(bufferRaw)) !=-1) {
  173.                
  174.                 // bufferizzo (1024 byte = 1kb alla volta)
  175.                 bufferReaded.write(bufferRaw, 0, lettiBuffer);
  176.                 kbLetti++;
  177.                 if(letturaPrecedente>0) {
  178.                     bLetti = bLetti + letturaPrecedente;
  179.                 }
  180.                 letturaPrecedente = lettiBuffer;
  181.            
  182.                 // In caso di charset differente, uso una stringa
  183.                 String bufferString = null;
  184.                 if(charset!=null) {
  185.                     ByteArrayOutputStream bufferTmp = new ByteArrayOutputStream();
  186.                     bufferTmp.write(bufferRaw, 0, lettiBuffer);
  187.                     bufferTmp.flush();
  188.                     bufferTmp.close();
  189.                     bufferString = new String(bufferTmp.toByteArray(), charset);
  190.                     lettiBuffer = bufferString.length();
  191.                 }
  192.                
  193.                 // analizzo
  194.                 for (int i = 0; i < lettiBuffer; i++) {
  195.                     char c = bufferString!=null ? bufferString.charAt(i) : (char) bufferRaw[i];
  196.                    
  197.                     if(headerCompletato && this.endHeaderOffset<=0) {
  198.                         this.endHeaderOffset = sbActualOffsetStart;
  199.                     }
  200.                    
  201.                     if( (c == '<' || startsWithLessThan(sbActual))
  202.                             &&
  203.                             !cdataFound &&
  204.                             !commentFound) {
  205.                                                
  206.                         if(sbActual!=null) {
  207.                             if(sbActual.length()>0) {
  208.                                
  209.                                 // devo verificare se ho incontrato un cdata o sto continuando a leggere un header
  210.                                 String sPreClosure = sbActual.toString();
  211.                                 sbActual.setLength(0);
  212.                                 sbActualOffsetStart = i+bLetti;
  213.                                
  214.                                 if(sPreClosure.startsWith("<![CDATA[")) {
  215.                                     //System.out.println("FOND CDATA! in sPreClosure");
  216.                                     cdataFound=true;
  217.                                 }
  218.                                 else if(sPreClosure.startsWith("<!--")) {
  219.                                     //System.out.println("FOND <!-- COMMENTO in sPreClosure: ["+sPreClosure+"]");
  220.                                     if(!sPreClosure.endsWith("-->")){
  221.                                         commentFound=true;
  222.                                     }
  223.                                 }
  224.                                
  225.                                 if(headerClosure!=null) {
  226.                                     //System.out.println("AGGIUNGO AD HEADER TESTO ["+sPreClosure+"]");
  227.                                     headerBuilder.append(sPreClosure);
  228.                                 }
  229.                                 else if(bodyFound) {
  230.                                     if(!sPreClosure.startsWith("<![CDATA[") && !sPreClosure.startsWith("<!--")) {
  231.                                         //System.out.println("AGGIUNGO A BODY ["+sPreClosure+"]");
  232.                                         if(elementAfterBodyBuilder!=null) {
  233.                                             elementAfterBodyBuilder.append(sPreClosure);
  234.                                         }
  235.                                         else {
  236.                                             elementAfterBodyBuilder = new StringBuilder(sPreClosure);
  237.                                         }
  238.                                     }
  239.                                 }
  240.                                
  241.                             }
  242.                         }
  243.                         else {
  244.                             sbActual = new StringBuilder();
  245.                             sbActualOffsetStart = i+bLetti;
  246.                         }
  247.                     }
  248.                     if(sbActual!=null) {
  249.                         sbActual.append(c);
  250.                     }
  251.                     if(c == '>' || endsWithGreaterThan(sbActual)) {
  252.                        
  253.                         if(sbActual==null) {
  254.                             //NO: gli attachments potrebbero rientrare in questo caso
  255.                             if(multipart) {
  256.                                 continue;
  257.                             }
  258.                             else {
  259.                                 throw new Exception("Invalid content; found premature '>' character ("+bufferReaded.toString()+")");
  260.                             }
  261.                         }
  262.                        
  263.                         String s = sbActual.toString();
  264.                        
  265.                         //System.out.println("S ["+s+"]");
  266.                        
  267.                         if(cdataFound) {
  268.                             if(headerClosure!=null) {
  269.                                 //System.out.println("AGGIUNGO AD HEADER CDATA ["+sbActual.toString()+"]");
  270.                                 headerBuilder.append(sbActual.toString());
  271.                             }
  272.                             sbActual.setLength(0);
  273.                             sbActualOffsetStart = i+bLetti;
  274.                             //System.out.println("continuo perche CDATA... ");
  275.                             if(s.endsWith("]]>")) {
  276.                                 cdataFound=false;
  277.                                 //System.out.println("FOUND FINE CDATA");
  278.                             }
  279.                             continue;
  280.                         }
  281.                         if(s.startsWith("<![CDATA[")) {
  282.                             //System.out.println("FOUND CDATA!");
  283.                             cdataFound=true;
  284.                             continue;
  285.                         }
  286.                        
  287.                         if(commentFound) {
  288.                             if(headerClosure!=null) {
  289.                                 //System.out.println("AGGIUNGO AD HEADER COMMENTO ["+sbActual.toString()+"]");
  290.                                 headerBuilder.append(sbActual.toString());
  291.                             }
  292.                             sbActual.setLength(0);
  293.                             sbActualOffsetStart = i+bLetti;
  294.                             //System.out.println("continuo perche COMMENTO... ");
  295.                             if(s.endsWith("-->")) {
  296.                                 commentFound=false;
  297.                                 //System.out.println("FOUND FINE COMMENTO");
  298.                             }
  299.                             continue;
  300.                         }
  301.                         if(s.startsWith("<!--")) {
  302.                             //System.out.println("FOUND <!-- COMMENTO: ["+s+"]");
  303.                             if(s.endsWith("-->")){
  304.                                 if(headerClosure!=null) {
  305.                                     //System.out.println("AGGIUNGO AD HEADER COMMENTO ["+sbActual.toString()+"]");
  306.                                     headerBuilder.append(sbActual.toString());
  307.                                 }
  308.                                 sbActual.setLength(0);
  309.                                 sbActualOffsetStart = i+bLetti;
  310.                             }
  311.                             else {
  312.                                 commentFound=true;
  313.                             }
  314.                             continue;
  315.                         }
  316.                        
  317.                         if(s.startsWith("<?")) {
  318.                             continue;
  319.                         }
  320.                        
  321.                         if(!envelopeFound && isOpenedElement(s,"<Envelope")) {
  322.                             this.envelope = s;
  323.                             //System.out.println("INIZIALIZZO ENVELOPE ["+s+"]");
  324.                             if(!analizyEnvelopeNamespace(this.envelope)) {
  325.                                 //System.out.println("TERMINO");
  326.                                 analisiTerminata=true;
  327.                                 break;
  328.                             }
  329.                             envelopeFound = true;
  330.                             this.prefixEnvelope = "";
  331.                         }
  332.                         else if(!envelopeFound && isOpenedElement(s,":Envelope")) {
  333.                             String sPrefix = s.substring(0, s.indexOf(":Envelope"));
  334.                             if(sPrefix.startsWith("<") && !sPrefix.contains(" ") && sPrefix.length()>1) {
  335.                                 this.envelope = s;
  336.                                 //System.out.println("INIZIALIZZO ENVELOPE ["+s+"]");
  337.                                 if(!analizyEnvelopeNamespace(this.envelope)) {
  338.                                     //System.out.println("TERMINO");
  339.                                     analisiTerminata=true;
  340.                                     break;
  341.                                 }
  342.                                 envelopeFound = true;
  343.                                 this.prefixEnvelope = sPrefix.substring(1)+":";
  344.                             }
  345.                             else {
  346.                                 analisiTerminata=true;
  347.                                 break;
  348.                             }
  349.                         }
  350.                         else if(envelopeFound) {
  351.                        
  352.                             if(headerClosure!=null) {
  353.                                 //System.out.println("AGGIUNGO AD HEADER ["+s+"]");
  354.                                 headerBuilder.append(s);
  355.                                 sbActual.setLength(0);
  356.                                 sbActualOffsetStart = i+bLetti;
  357.                                 if(s.startsWith(headerClosure)) {
  358.                                     headerClosure=null;
  359.                                     headerCompletato = true;
  360.                                 }
  361.                                 continue;
  362.                             }
  363.                            
  364.                             if(headerBuilder==null && isOpenedElement(s,"<Header")) {
  365.                                 //System.out.println("INIZIALIZZO HEADER ["+s+"]");
  366.                                 //headerBuilder = new StringBuilder(s);
  367.                                 headerBuilder = new StringBuilder();
  368.                                 if(!s.endsWith("/>")) {
  369.                                     headerClosure = "</Header";
  370.                                 }
  371.                                 if(bodyFound) {
  372.                                     analisiTerminata=true;
  373.                                     break;
  374.                                 }
  375.                                 else {
  376.                                     this.startHeaderOffset = sbActualOffsetStart;
  377.                                     this.prefixHeader = "";
  378.                                 }
  379.                             }
  380.                             else if(headerBuilder==null && isOpenedElement(s,":Header")) {
  381.                                 String sPrefix = s.substring(0, s.indexOf(":Header"));
  382.                                 if(sPrefix.startsWith("<") && !sPrefix.contains(" ") && sPrefix.length()>1) {
  383.                                     //System.out.println("INIZIALIZZO HEADER ["+s+"]");
  384.                                     //headerBuilder = new StringBuilder(s);
  385.                                     headerBuilder = new StringBuilder();
  386.                                     if(!s.endsWith("/>")) {
  387.                                         headerClosure = "</"+sPrefix.substring(1)+":"+"Header";
  388.                                     }
  389.                                     if(bodyFound) {
  390.                                         analisiTerminata=true;
  391.                                         break;
  392.                                     }
  393.                                     else {
  394.                                         this.startHeaderOffset = sbActualOffsetStart;
  395.                                         this.prefixHeader = sPrefix.substring(1)+":";
  396.                                     }
  397.                                 }
  398.                                 else {
  399.                                     analisiTerminata=true;
  400.                                     break;
  401.                                 }
  402.                             }
  403.                             else if(!bodyFound && isOpenedElement(s,"<Body")) {
  404.                                 //System.out.println("INIZIALIZZO BODY ["+s+"]");
  405.                                 this.body = s;
  406.                                 bodyFound = true;
  407.                                 prefixBody = "";
  408.                                 if(this.startHeaderOffset<=0) {
  409.                                     this.startHeaderOffset = sbActualOffsetStart;
  410.                                 }
  411.                                 this.startBodyOffset=sbActualOffsetStart;
  412.                                 sbActual.setLength(0);
  413.                                 sbActualOffsetStart = i+bLetti;
  414.                             }
  415.                             else if(!bodyFound && isOpenedElement(s,":Body")) {
  416.                                 String sPrefix = s.substring(0, s.indexOf(":Body"));
  417.                                 if(sPrefix.startsWith("<") && !sPrefix.contains(" ") && sPrefix.length()>1) {
  418.                                     //System.out.println("INIZIALIZZO BODY ["+s+"]");
  419.                                     this.body = s;
  420.                                     bodyFound = true;
  421.                                     prefixBody = sPrefix.substring(1)+":";
  422.                                     if(this.startHeaderOffset<=0) {
  423.                                         this.startHeaderOffset = sbActualOffsetStart;
  424.                                     }
  425.                                     this.startBodyOffset=sbActualOffsetStart;
  426.                                     sbActual.setLength(0);
  427.                                     sbActualOffsetStart = i+bLetti;
  428.                                 }
  429.                                 else {
  430.                                     analisiTerminata=true;
  431.                                     break;
  432.                                 }
  433.                             }
  434.                             else if(bodyFound) {
  435.                                 if(this.fault==null && isOpenedElement(s,"<Fault")) {
  436.                                     //System.out.println("INIZIALIZZO FAULT ["+s+"]");
  437.                                     this.fault = s;
  438.                                 }
  439.                                 else if(this.fault==null && isOpenedElement(s,":Fault")) {
  440.                                     String sPrefix = s.substring(0, s.indexOf(":Fault"));
  441.                                     if(sPrefix.startsWith("<") && !sPrefix.contains(" ")) {
  442.                                         //System.out.println("INIZIALIZZO FAULT ["+s+"]");
  443.                                         this.fault = s;
  444.                                     }
  445.                                 }
  446.                                 else {
  447.                                    
  448.                                     String closeBody = "</"+prefixBody+"Body";
  449.                                     String closeEnvelope = "</"+this.prefixEnvelope+"Envelope";
  450.                                     if( isClosedElement(s,closeBody) || isClosedElement(s,closeEnvelope) ){
  451.                                         this.parsingComplete = true;
  452.                                     }
  453.                                     else {
  454.                                         if(!endsWithGreaterThan(s)){
  455.                                             if(elementAfterBodyBuilder!=null) {
  456.                                                 //System.out.println("AGGIUNGO A BODY dentro ["+s+"]");
  457.                                                 elementAfterBodyBuilder.append(s);
  458.                                             }
  459.                                             else {
  460.                                                 //System.out.println("CREO A BODY ["+s+"]");
  461.                                                 elementAfterBodyBuilder = new StringBuilder(s);
  462.                                             }
  463.                                         }
  464.                                     }
  465.                                    
  466.                                     analisiTerminata=true;
  467.                                     break;
  468.                                 }
  469.                             }
  470.                            
  471.                         }
  472.                     }
  473.                    
  474.                 }
  475.                 if(analisiTerminata) {
  476.                     break;
  477.                 }
  478.                 if(kbLetti==this.bufferThresholdKb) {
  479.                     // buffer dimensione massima raggiunta
  480.                     break;
  481.                 }
  482.             }
  483.            
  484.             // svuoto
  485.             if(sbActual!=null) {
  486.                 if(sbActual.length()>0) {
  487.                     sbActual.setLength(0);
  488.                 }
  489.             }
  490.            
  491.            
  492.             bufferReaded.flush();
  493.             bufferReaded.close();
  494.             if(bufferReaded.size()>0) {
  495.                 this.bufferSize = bufferReaded.size();
  496.                 ByteArrayInputStream bin = new ByteArrayInputStream(bufferReaded.toByteArray());
  497.                 if(lettiBuffer!=-1) {
  498.                     // sono uscita prima della chiusura dello stream
  499.                     this.bufferedInputStream = new SequenceInputStream(bin,this.is);
  500.                 }
  501.                 else {
  502.                     // letto tutto
  503.                     this.bufferedInputStream = bin;
  504.                 }
  505.             }
  506.            
  507.            
  508.             boolean throwException = false;
  509.             String elementAfterBody = null;
  510.             //System.out.println("BODY ["+elementAfterBodyBuilder+"]");
  511.             if(elementAfterBodyBuilder!=null && elementAfterBodyBuilder.length()>0) {
  512.                 elementAfterBody = elementAfterBodyBuilder.toString();
  513.             }
  514.             if(elementAfterBody!=null || this.fault!=null) {
  515.                 throwException=true; // ho terminato di leggere la parte interessante del messaggio
  516.                 this.parsingComplete = true;
  517.             }

  518.             if(headerBuilder!=null && headerBuilder.length()>0) {
  519.                 if(this.envelope.endsWith("/>")) {
  520.                     if(throwException) {
  521.                         throw new Exception("Invalid content; found 'Header' after envelope closure '/>': ("+headerBuilder+")");
  522.                     }
  523.                     else{
  524.                         return;
  525.                     }
  526.                 }
  527.                 if(headerCompletato) {
  528.                     StringBuilder sbHeaderAnalizer = new StringBuilder();
  529.                     sbHeaderAnalizer.append(this.envelope);
  530.                     sbHeaderAnalizer.append(headerBuilder.toString());
  531.                     sbHeaderAnalizer.append("<").append(this.prefixEnvelope).append("Body/>");
  532.                     sbHeaderAnalizer.append("</").append(this.prefixEnvelope).append("Envelope>");
  533.                     this.header = sbHeaderAnalizer.toString();
  534.                 }
  535.             }
  536.             if(this.body!=null) {
  537.                 //System.out.println("BODY ["+this.body+"]");
  538.                 if(this.envelope.endsWith("/>")) {
  539.                     if(throwException) {
  540.                         throw new Exception("Invalid content; found 'Body' after envelope closure '/>': ("+this.body+")");
  541.                     }
  542.                     else{
  543.                         return;
  544.                     }
  545.                 }
  546.                 if(this.body.endsWith("/>")) {
  547.                     this.bodyEmpty = true;
  548.                 }
  549.             }
  550.            
  551.             if(this.fault!=null) {
  552.                 //System.out.println("TROVATO FAULT ["+this.fault+"]");
  553.                 if(this.body.endsWith("/>")) {
  554.                     if(throwException) {
  555.                         throw new Exception("Invalid content; found Fault after body closure '/>': ("+this.fault+")");
  556.                     }
  557.                     else{
  558.                         return;
  559.                     }
  560.                 }
  561.                 StringBuilder sbFaultAnalizer = new StringBuilder();
  562.                 sbFaultAnalizer.append(this.envelope);
  563.                 sbFaultAnalizer.append(this.body);
  564.                 sbFaultAnalizer.append(this.fault);
  565.                 if((this.fault.contains("<") && this.fault.contains(">")) && !this.fault.trim().endsWith("/>")) {
  566.                     //System.out.println("CALCOLO!! ["+this.fault+"]");
  567.                     int i = 0;
  568.                     for (; i < this.fault.length(); i++) {
  569.                         char c = this.fault.charAt(i);
  570.                         if(c=='<') {
  571.                             i++;
  572.                             break;
  573.                         }
  574.                     }
  575.                     //System.out.println("DOPO GIRO: "+i);
  576.                     StringBuilder sb = new StringBuilder();
  577.                     for (; i < this.fault.length(); i++) {
  578.                         char c = this.fault.charAt(i);
  579.                         if(c==' ' || c=='>' || c=='\t' || c=='\r' || c=='\n') {
  580.                             break;
  581.                         }
  582.                         sb.append(c);
  583.                     }
  584.                     sbFaultAnalizer.append("</").append(sb.toString()).append(">");
  585.                     //System.out.println("TROVATO:["+sb.toString()+"]");
  586.                 }
  587.                
  588.                 sbFaultAnalizer.append("</").append(prefixBody).append("Body>");
  589.                 sbFaultAnalizer.append("</").append(this.prefixEnvelope).append("Envelope>");
  590.                 //Element e = null;
  591.                 String namespaceFaultTrovato = null;
  592.                 try {
  593.                     OpenSPCoop2Message msg = buildOp2Message(sbFaultAnalizer.toString().getBytes(), this.getMessageType());
  594.                     SOAPBody soapBody = msg.castAsSoap().getSOAPBody();
  595.                     if(soapBody!=null) {
  596.                         if(soapBody.hasFault()) {
  597.                             namespaceFaultTrovato = soapBody.getFault().getNamespaceURI();
  598.                         }
  599.                     }
  600.                 }catch(Throwable t) {
  601.                     if(throwException) {
  602.                         throw new Exception("Invalid content ("+sbFaultAnalizer.toString()+"): "+t.getMessage(),t);
  603.                     }
  604.                     else{
  605.                         return;
  606.                     }
  607.                 }
  608.                 if(!this.namespace.equals(namespaceFaultTrovato)) {
  609.                     elementAfterBody = this.fault;
  610.                     this.fault = null; // si tratta di un contenuto applicativo con nome Fault
  611.                 }
  612.             }
  613.            
  614.            
  615.             if(this.fault==null && elementAfterBody!=null) {
  616.                 //System.out.println("elementAfterBody ["+elementAfterBody+"]");

  617.                 StringBuilder sbElementAnalizer = new StringBuilder();
  618.                 sbElementAnalizer.append(this.envelope);
  619.                 sbElementAnalizer.append(this.body);
  620.                 sbElementAnalizer.append(elementAfterBody);
  621.                 if((elementAfterBody.contains("<") && elementAfterBody.contains(">")) && !elementAfterBody.trim().endsWith("/>")) {
  622.                     //System.out.println("CALCOLO!! ["+elementAfterBody+"]");
  623.                     int i = 0;
  624.                     for (; i < elementAfterBody.length(); i++) {
  625.                         char c = elementAfterBody.charAt(i);
  626.                         if(c=='<') {
  627.                             i++;
  628.                             break;
  629.                         }
  630.                     }
  631.                     //System.out.println("DOPO GIRO: "+i);
  632.                     StringBuilder sb = new StringBuilder();
  633.                     for (; i < elementAfterBody.length(); i++) {
  634.                         char c = elementAfterBody.charAt(i);
  635.                         if(c==' ' || c=='>' || c=='\t' || c=='\r' || c=='\n') {
  636.                             break;
  637.                         }
  638.                         sb.append(c);
  639.                     }
  640.                     sbElementAnalizer.append("</").append(sb.toString()).append(">");
  641.                     //System.out.println("TROVATO:["+sb.toString()+"]");
  642.                 }
  643.                 else {
  644.                     //System.out.println("RIPULISCO");
  645.                     boolean empty = true;
  646.                     for (int i = 0; i < elementAfterBody.length(); i++) {
  647.                         char c = elementAfterBody.charAt(i);
  648.                         if(c!=' ' && c!='\t' && c!='\r' && c!='\n') {
  649.                             empty = false;
  650.                             break;
  651.                         }
  652.                     }
  653.                     //System.out.println("RIPULISCO EMPTY: "+empty);
  654.                     if(empty) {
  655.                         this.bodyEmpty=true;
  656.                     }
  657.                 }
  658.                
  659.                 //System.out.println("BODY ["+this.body+"]");
  660.                 if(this.body!=null && this.body.endsWith("/>")) {
  661.                     if(!this.bodyEmpty) {
  662.                         if(throwException) {
  663.                             throw new Exception("Invalid content; found element after body closure '/>': ("+elementAfterBody+")");
  664.                         }
  665.                         else{
  666.                             return;
  667.                         }
  668.                     }
  669.                 }
  670.                 else {
  671.                
  672.                     sbElementAnalizer.append("</").append(prefixBody).append("Body>");
  673.                     sbElementAnalizer.append("</").append(this.prefixEnvelope).append("Envelope>");
  674.                     //System.out.println("UTILIZZO:["+sbElementAnalizer.toString()+"]");
  675.                     //Element e = null;
  676.                     SAXParser saxParser = null;
  677.                     try {
  678.                         //e = XMLUtils.getInstance().newElement(sbElementAnalizer.toString().getBytes());
  679.                        
  680.                         saxParser = getParser();
  681.                         XMLReader xmlReader = saxParser.getXMLReader();
  682.                         RootElementSaxContentHandler saxHandler = new RootElementSaxContentHandler(this.namespace);
  683.                         xmlReader.setContentHandler(saxHandler);
  684.                         //System.out.println("ANALIZZO '"+sbElementAnalizer.toString()+"'");
  685.                         try(ByteArrayInputStream bin = new ByteArrayInputStream(sbElementAnalizer.toString().getBytes())){
  686.                             InputSource inputSource = new InputSource(bin);
  687.                             xmlReader.parse(inputSource);
  688.                         }
  689.                         this.rootElementLocalName = saxHandler.getLocalName();
  690.                         this.rootElementNamespace = saxHandler.getNamespace();  
  691.                         this.rootElementPrefix = saxHandler.getPrefix();
  692.                     }catch(Throwable t) {
  693.                         if(throwException) {
  694.                             throw new Exception("Invalid content '"+elementAfterBody+"' ("+sbElementAnalizer.toString()+"): "+t.getMessage(),t);
  695.                         }
  696.                         else{
  697.                             return;
  698.                         }
  699.                     }finally {
  700.                         if(saxParser!=null) {
  701.                             returnParser(saxParser);
  702.                         }
  703.                     }
  704.     //              Node body = SoapUtils.getFirstNotEmptyChildNode(this.msgFactory, e, false);
  705.     //              if(body!=null) {
  706.     //                  Node element = SoapUtils.getFirstNotEmptyChildNode(this.msgFactory, body, false);
  707.     //                  if(element instanceof Element) {
  708.     //                      this.rootElement = (Element) element;
  709.     //                  }
  710.     //              }
  711.                 }
  712.                
  713.             }
  714.            
  715.             if(this.fault==null && elementAfterBody==null) {
  716.                 if(this.parsingComplete) { // siamo arrivato alla chiusura del body o dell'envelope
  717.                     this.bodyEmpty=true;
  718.                 }
  719.             }
  720.            
  721.            
  722.             //System.out.println("parsingComplete["+this.parsingComplete+"] charset["+charset+"] startHeaderOffset["+this.startHeaderOffset+"] < endHeaderOffset["+this.endHeaderOffset+"] < startBodyOffset["+this.startBodyOffset+"]");
  723.             if(this.parsingComplete) {
  724.                 if(charset==null || !charset.startsWith("UTF-16")) {
  725.                     if(this.startHeaderOffset>0 && this.startBodyOffset>=this.startHeaderOffset) {
  726.                         this.soapHeaderOptimizable = true;
  727.                         if(this.endHeaderOffset>0) {
  728.                             if(this.endHeaderOffset<this.startHeaderOffset || this.endHeaderOffset>this.startBodyOffset) {
  729.                                 // inconsistenza
  730.                                 this.soapHeaderOptimizable = false;
  731.                             }
  732.                         }
  733.                     }
  734.                 }
  735.             }
  736.            
  737.         }catch(Throwable t) {
  738.             this.tBuffered = new MessageException(t.getMessage(),t);
  739.             throw this.tBuffered;
  740.         }
  741.        
  742.         return;
  743.        
  744.     }
  745.     private boolean endsWithGreaterThan( String s ) {
  746.         if ( s == null || s.length() < 4 )
  747.             return false;
  748.         int startIx = s.length() - 4;
  749.         return ( s.charAt(startIx) == '&' && s.charAt(startIx + 1) == 'g' && s.charAt(startIx + 2) == 't' && s.charAt(startIx + 3) == ';' );
  750.     }
  751.     private boolean endsWithGreaterThan( StringBuilder buffer ) {
  752.         if ( buffer == null || buffer.length() < 4 )
  753.             return false;
  754.         int startIx = buffer.length() - 4;
  755.         return ( buffer.charAt(startIx) == '&' && buffer.charAt(startIx + 1) == 'g' && buffer.charAt(startIx + 2) == 't' && buffer.charAt(startIx + 3) == ';' );
  756.     }
  757.     private boolean startsWithLessThan( StringBuilder buffer ) {
  758.         if ( buffer == null || buffer.length() < 4 )
  759.             return false;
  760.         return ( buffer.charAt(0) == '&' && buffer.charAt(1) == 'l' && buffer.charAt(2) == 't' && buffer.charAt(3) == ';' );
  761.     }
  762.    
  763.     private boolean isOpenedElement(String s, String prefix) {
  764.         if(prefix.startsWith(":")) {
  765.             return s.contains(prefix+" ") || s.contains(prefix+">") || s.contains(prefix+"/")  ||
  766.                     s.contains(prefix+"\n") || s.contains(prefix+"\r") || s.contains(prefix+"\t");
  767.         }
  768.         else {
  769.             return s.startsWith(prefix+" ") || s.startsWith(prefix+">") || s.startsWith(prefix+"/")  ||
  770.                     s.startsWith(prefix+"\n") || s.startsWith(prefix+"\r") || s.startsWith(prefix+"\t");
  771.         }
  772.     }
  773.     private boolean isClosedElement(String s, String prefix) {
  774.         return s.startsWith(prefix+" ") || s.startsWith(prefix+">") ||
  775.                 s.startsWith(prefix+"\n") || s.startsWith(prefix+"\r") || s.startsWith(prefix+"\t");
  776.     }
  777.    
  778.     private boolean analizyEnvelopeNamespace(String envelope) throws Exception {
  779.         if(envelope!=null) {
  780.             String s = null;
  781.             if(envelope.endsWith("/>")) {
  782.                 s = envelope;
  783.             }
  784.             else {
  785.                 s = envelope.replace(">", "/>");
  786.             }
  787.            
  788.             //Element e = XMLUtils.getInstance().newElement(s.getBytes());
  789.             //this.namespace = e.getNamespaceURI();
  790.             //System.out.println("ENVELOPE PARSE ["+envelope+"]");
  791.             SAXParser saxParser = null;
  792.             try {
  793.                 saxParser = getParser();
  794.                 XMLReader xmlReader = saxParser.getXMLReader();
  795.                 SoapEnvelopeSaxContentHandler saxHandler = new SoapEnvelopeSaxContentHandler();
  796.                 xmlReader.setContentHandler(saxHandler);
  797.                 try(ByteArrayInputStream bin = new ByteArrayInputStream(s.getBytes())){
  798.                     InputSource inputSource = new InputSource(bin);
  799.                     xmlReader.parse(inputSource);
  800.                 }
  801.                 this.namespace = saxHandler.getNamespace();
  802.                 //System.out.println("ENVELOPE PARSE ["+envelope+"], found namespace: "+this.namespace);
  803.             }
  804.             catch(Throwable t) {
  805.                 throw new Exception("Invalid content ("+s+"): "+t.getMessage(),t);
  806.             }
  807.             finally {
  808.                 if(saxParser!=null) {
  809.                     returnParser(saxParser);
  810.                 }
  811.             }
  812.            
  813.            
  814.             return Costanti.SOAP_ENVELOPE_NAMESPACE.equals(this.namespace) ||
  815.                     Costanti.SOAP12_ENVELOPE_NAMESPACE.equals(this.namespace);
  816.         }
  817.         return false;
  818.     }

  819.     public String getEnvelope() {
  820.         return this.envelope;
  821.     }

  822.     public String getNamespace() {
  823.         return this.namespace;
  824.     }
  825.    
  826.     public MessageType getMessageType() {
  827.         if(Costanti.SOAP_ENVELOPE_NAMESPACE.equals(this.namespace)) {
  828.             return MessageType.SOAP_11;
  829.         }
  830.         else {
  831.             return MessageType.SOAP_12;
  832.         }
  833.     }

  834.     public boolean isParsingComplete() {
  835.         return this.parsingComplete;
  836.     }
  837.    
  838. //  public String getBody() {
  839. //      return this.body;
  840. //  }

  841.     public boolean isFault() {
  842.         return this.fault!=null;
  843.     }
  844.    
  845.     public boolean isEmpty() {
  846.         return this.bodyEmpty;
  847.     }
  848.    
  849.     public int getBufferSize() {
  850.         return this.bufferSize;
  851.     }
  852.    
  853.     public OpenSPCoop2Message getHeader_OpenSPCoop2Message() throws MessageException {
  854.         boolean checkIsEmpty = true;
  855.         SOAPHeader s = _getHeader(checkIsEmpty, false); // perchè la struttura del soap header viene mantenuta anche vuota, per preservare i commenti.
  856.         if(s!=null) {
  857.             return this._headerMsgCompleto;
  858.         }
  859.         return null;
  860.     }
  861.     public SOAPHeader getHeader() throws MessageException {
  862.         return _getHeader(false, false);
  863.     }
  864.     public SOAPHeader getModifiableHeader() throws MessageException {
  865.         this.soapHeaderModified = true;
  866.         return _getHeader(false, false);
  867.     }
  868.     public SOAPHeader addHeader() throws MessageException {
  869.         return _getHeader(false, true);
  870.     }
  871.     public boolean isSoapHeaderModified() {
  872.         return this.soapHeaderModified;
  873.     }
  874.     public void setSoapHeaderModified(boolean soapHeaderModified) {
  875.         this.soapHeaderModified = soapHeaderModified;
  876.     }
  877.     private MessageException parseErrorHeader = null;
  878.     private SOAPHeader _getHeader(boolean checkIsEmpty, boolean buildIfEmpty) throws MessageException {
  879.        
  880.         if(this.parseErrorHeader!=null) {
  881.             throw this.parseErrorHeader;
  882.         }
  883.        
  884.         SOAPHeader soapHeader = null;
  885.        
  886.         if(this._headerMsgCompleto!=null) {
  887.             try{
  888.                 soapHeader = this._headerMsgCompleto.castAsSoap().getSOAPHeader();
  889.             }catch(Throwable t) {
  890.                 throw SoapUtils.buildMessageException("Error during access header: "+t.getMessage(),t);
  891.             }
  892.         }
  893.         else {
  894.             if(this._headerMsgCompleto==null && this.header!=null) {
  895.                 try {
  896.                     //System.out.println("COSTRUISCO ["+this.header+"]");
  897.                     this._headerMsgCompleto = buildOp2Message(this.header.getBytes(), this.getMessageType());
  898.                     soapHeader = this._headerMsgCompleto.castAsSoap().getSOAPHeader();
  899.                     //System.out.println("COSTRUITO ["+org.openspcoop2.message.xml.XMLUtils.getInstance(this.msgFactory).toString(soapHeader)+"]");
  900.                                        
  901.                     if(soapHeader!=null) {
  902.                         if("".equals(this.prefixEnvelope)) {
  903.                             this._headerMsgCompleto.castAsSoap().getSOAPPart().getEnvelope().setPrefix("");
  904.                         }
  905.                         if("".equals(this.prefixHeader)) {
  906.                             soapHeader.setPrefix("");
  907.                         }
  908.                         //System.out.println("HEADER COSTRUITO DA QUANTO LETTO CON SAAJ PREFIX ["+soapHeader.getPrefix()+"], LETTO: "+this.header);
  909.                     }
  910.                    
  911.                     //this._header = XMLUtils.getInstance().newElement(this.header.getBytes());
  912.                    
  913.                     this.header = null; // libero memoria
  914.                    
  915.                 }catch(Throwable t) {
  916.                     //System.out.println("ECCEZIONE!");
  917.                     this.parseErrorHeader = SoapUtils.buildMessageException("Invalid header ("+this.header+"): "+t.getMessage(),t);
  918.                     throw this.parseErrorHeader;
  919.                 }
  920.             }
  921.            
  922.             if(this._headerMsgCompleto==null && buildIfEmpty) {
  923.                 try {
  924.                     String xmlns = "";
  925.                     if(this.prefixEnvelope!=null && !"".equals(this.prefixEnvelope)) {
  926.                         xmlns=":"+this.prefixEnvelope;
  927.                         if(xmlns.endsWith(":") && xmlns.length()>1) {
  928.                             xmlns = xmlns.substring(0, xmlns.length()-1);
  929.                         }
  930.                     }
  931.                     String envelope = "<"+this.prefixEnvelope+"Envelope xmlns"+xmlns+"=\""+this.namespace+"\"><"+this.prefixEnvelope+"Header/></"+this.prefixEnvelope+"Envelope>";
  932.                     this._headerMsgCompleto = buildOp2Message(envelope.getBytes(), this.getMessageType());
  933.                     soapHeader = this._headerMsgCompleto.castAsSoap().getSOAPHeader();
  934.                     if("".equals(xmlns)) {
  935.                         this._headerMsgCompleto.castAsSoap().getSOAPPart().getEnvelope().setPrefix("");
  936.                         soapHeader.setPrefix("");
  937.                     }
  938.                     //System.out.println("HEADER CREATO CON SAAJ PREFIX ["+soapHeader.getPrefix()+"]");
  939.                     this.soapHeaderModified = true;
  940.                 }catch(Throwable t) {
  941.                     throw SoapUtils.buildMessageException("Build header failed: "+t.getMessage(),t);
  942.                 }
  943.             }
  944.         }
  945.        
  946.         if(soapHeader!=null && checkIsEmpty) {
  947.             Node n = SoapUtils.getFirstNotEmptyChildNode(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), soapHeader, false);
  948.             if(n==null) {
  949.                 soapHeader = null;
  950.             }
  951.         }
  952.        
  953.         /*if(soapHeader!=null) {
  954.             try {
  955.                 TransformerConfig xmlConfig = new TransformerConfig();
  956.                 xmlConfig.setOmitXMLDeclaration(true);
  957.                 xmlConfig.setCharset(this.isCharset);
  958.                 System.out.println("COSTRUITO ["+org.openspcoop2.message.xml.XMLUtils.getInstance(OpenSPCoop2MessageFactory.getDefaultMessageFactory()).toString(soapHeader, xmlConfig)+"]");
  959.                 org.w3c.dom.NodeList l = soapHeader.getChildNodes();
  960.                 for (int i = 0; i < l.getLength(); i++) {
  961.                     System.out.println("BEFORE ["+l.item(i).getClass().getName()+"] ["+l.item(i).getLocalName()+"]");
  962.                 }
  963.             }catch(Throwable t) {
  964.                 System.out.println("ERRORE");
  965.             }
  966.         }*/
  967.        
  968.         return soapHeader;
  969.     }
  970.     public void clearHeader() {
  971.         this._headerMsgCompleto=null;
  972.         this.soapHeaderOptimizable=false;
  973.     }


  974. //  public Element getRootElement() {
  975. //      return this.rootElement;
  976. //  }
  977.     public String getRootElementNamespace() {
  978.         return this.rootElementNamespace;
  979.     }
  980.     public String getRootElementLocalName() {
  981.         return this.rootElementLocalName;
  982.     }
  983.     public String getRootElementPrefix() {
  984.         return this.rootElementPrefix;
  985.     }
  986.    
  987.     private static ThreadLocal<SAXParser> saxParserThreadLocal =
  988.                 new ThreadLocal<SAXParser>() {
  989.             @Override
  990.             protected SAXParser initialValue() {
  991.                 try{
  992.                     SAXParserFactory saxFactory = XMLUtils.getInstance().getSAXParserFactory();
  993. //                  try {
  994. //                      saxFactory.setFeature("jdk.xml.resetSymbolTable", true);
  995. //                  } catch(Throwable e) {
  996. //                  }
  997.                     saxFactory.setNamespaceAware(true);
  998.                     SAXParser parser = saxFactory.newSAXParser();
  999.                     return parser;
  1000.                 }catch(Throwable t){
  1001.                     throw new RuntimeException("Inizializzazione SAXParser fallita: "+t.getMessage(),t);
  1002.                 }
  1003.             }
  1004.     };
  1005.     private static SAXParser getParser() {
  1006.         return saxParserThreadLocal.get();
  1007.     }
  1008.     public static void removeParser() {
  1009.         saxParserThreadLocal.remove();
  1010.     }
  1011.            
  1012.     private static void returnParser(SAXParser saxParser) {
  1013.         saxParser.reset();
  1014.     }
  1015.    
  1016.     private static OpenSPCoop2Message buildOp2Message(byte[] bytes, MessageType messageType) throws Exception {
  1017.         MimeHeaders mhs = new MimeHeaders();
  1018.         mhs.addHeader(HttpConstants.CONTENT_TYPE, MessageType.SOAP_11.equals(messageType) ? HttpConstants.CONTENT_TYPE_SOAP_1_1 : HttpConstants.CONTENT_TYPE_SOAP_1_2);
  1019.         OpenSPCoop2Message msg = null;
  1020.         try(ByteArrayInputStream bin = new ByteArrayInputStream(bytes)){
  1021.             if(MessageType.SOAP_11.equals(messageType)){
  1022.                 msg = new OpenSPCoop2Message_saaj_11_impl(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), mhs, bin);
  1023.             }
  1024.             else {
  1025.                 msg = new OpenSPCoop2Message_saaj_12_impl(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), mhs, bin);
  1026.             }
  1027.         }
  1028.         return msg;
  1029.     }
  1030.    
  1031.     public boolean isSoapHeaderOptimizable() {
  1032.         return SOAP_HEADER_OPTIMIZATION_ENABLED && this.soapHeaderOptimizable;
  1033.     }
  1034.    
  1035.     public void writeOptimizedHeaderTo(InputStream is, OutputStream osParam, boolean consumeHeader) throws Exception {
  1036.         if(!this.soapHeaderOptimizable) {
  1037.             throw new Exception("SOAPHeader not optimizable");
  1038.         }
  1039.        
  1040.         if(this._headerMsgCompleto==null) {
  1041.             throw new Exception("SOAPMessage Optimized undefined");
  1042.         }
  1043.         SOAPHeader soapHeader = this._headerMsgCompleto.castAsSoap().getSOAPHeader();
  1044.         if(soapHeader==null) {
  1045.             throw new Exception("SOAPHeader undefined");
  1046.         }
  1047.        
  1048.         TransformerConfig xmlConfig = new TransformerConfig();
  1049.         xmlConfig.setOmitXMLDeclaration(true);
  1050.         xmlConfig.setCharset(this.isCharset);
  1051.                
  1052.         long indexBody = this.startBodyOffset;
  1053.         if(this.endHeaderOffset>0) {
  1054.             indexBody = this.endHeaderOffset+1;
  1055.         }
  1056.        
  1057.         // first
  1058.         byte[] buffer = new byte[Utilities.DIMENSIONE_BUFFER];
  1059.         int letti = 0;
  1060.         long index = 0;
  1061.         boolean writeHeader = false;
  1062.        
  1063.         boolean debug = false;
  1064.         OutputStream os = null;
  1065.         if(debug) {
  1066.             os = new ByteArrayOutputStream();
  1067.         }
  1068.         else {
  1069.             os = osParam;
  1070.         }
  1071.         while( (letti=is.read(buffer, 0, Utilities.DIMENSIONE_BUFFER)) != -1 ){
  1072.            
  1073.             if(index<this.startHeaderOffset) {
  1074.                 for (int i=0; i < letti; i++) {
  1075.                     if(!writeHeader || index>=indexBody) {
  1076.                         os.write(buffer[i]);
  1077.                     }
  1078.                     index++;
  1079.                    
  1080.                     if(index==this.startHeaderOffset) {
  1081.                         if(debug) {
  1082.                             os.flush();
  1083.                             //System.out.println("SCRITTO FINO A HEADER ["+os.toString()+"]");
  1084.                         }
  1085.                        
  1086.                         //os.write(OpenSPCoop2MessageFactory.getAsByte(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), this._header, true));
  1087.                         os.write(org.openspcoop2.message.xml.MessageXMLUtils.getInstance(OpenSPCoop2MessageFactory.getDefaultMessageFactory()).toByteArray(soapHeader, xmlConfig));
  1088.                         writeHeader = true;
  1089.                         if(debug) {
  1090.                             os.flush();
  1091.                             //System.out.println("SCRITTO HEADER ["+os.toString()+"]");
  1092.                         }
  1093.                     }
  1094.                 }
  1095.             }
  1096.             else {
  1097.                 if(!writeHeader) {
  1098.                     //os.write(OpenSPCoop2MessageFactory.getAsByte(OpenSPCoop2MessageFactory.getDefaultMessageFactory(), this._header, true));
  1099.                     os.write(org.openspcoop2.message.xml.MessageXMLUtils.getInstance(OpenSPCoop2MessageFactory.getDefaultMessageFactory()).toByteArray(soapHeader, xmlConfig));
  1100.                     writeHeader = true;
  1101.                     if(debug) {
  1102.                         os.flush();
  1103.                         //System.out.println("SCRITTO HEADER GIRO SUCCESSIVO ["+os.toString()+"]");
  1104.                     }
  1105.                 }
  1106.                 if(index>=indexBody) {
  1107.                     os.write(buffer, 0, letti);
  1108.                     index = index+letti;
  1109.                 }
  1110.                 else {
  1111.                     for (int i=0; i < letti; i++) {
  1112.                         if(index>=indexBody) {
  1113.                             os.write(buffer[i]);
  1114.                         }
  1115.                         index++;
  1116.                     }
  1117.                 }
  1118.                 if(debug) {
  1119.                     os.flush();
  1120.                     //System.out.println("SCRITTO PEZZO ["+os.toString()+"]");
  1121.                 }
  1122.             }
  1123.            
  1124.         }
  1125.                
  1126.         if(debug) {
  1127.             os.flush();
  1128.             //System.out.println("SCRITTO TUTTO ["+os.toString()+"]");
  1129.         }
  1130.        
  1131.        
  1132.         // flush
  1133.         os.flush();
  1134.        
  1135.         // ** rilascio memoria **
  1136.         if(consumeHeader) {
  1137.             this._headerMsgCompleto = null;
  1138.             this.soapHeaderOptimizable=false;
  1139.             this.bufferedInputStream = null;
  1140.         }
  1141.     }
  1142. }