SoapUtils.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;


  21. import java.io.ByteArrayOutputStream;
  22. import java.util.ArrayList;
  23. import java.util.Enumeration;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Locale;

  27. import javax.mail.internet.ContentType;
  28. import javax.mail.internet.ParseException;
  29. import javax.xml.namespace.QName;
  30. import javax.xml.soap.Detail;
  31. import javax.xml.soap.MessageFactory;
  32. import javax.xml.soap.MimeHeader;
  33. import javax.xml.soap.MimeHeaders;
  34. import javax.xml.soap.SOAPBody;
  35. import javax.xml.soap.SOAPElement;
  36. import javax.xml.soap.SOAPEnvelope;
  37. import javax.xml.soap.SOAPException;
  38. import javax.xml.soap.SOAPFactory;
  39. import javax.xml.soap.SOAPFault;
  40. import javax.xml.soap.SOAPHeader;
  41. import javax.xml.soap.SOAPHeaderElement;
  42. import javax.xml.soap.SOAPMessage;
  43. import javax.xml.soap.SOAPPart;
  44. import javax.xml.soap.Text;

  45. import org.openspcoop2.message.OpenSPCoop2Message;
  46. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  47. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  48. import org.openspcoop2.message.constants.Costanti;
  49. import org.openspcoop2.message.constants.MessageRole;
  50. import org.openspcoop2.message.constants.MessageType;
  51. import org.openspcoop2.message.constants.ServiceBinding;
  52. import org.openspcoop2.message.exception.MessageException;
  53. import org.openspcoop2.message.exception.MessageNotSupportedException;
  54. import org.openspcoop2.message.exception.ParseExceptionUtils;
  55. import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
  56. import org.openspcoop2.message.utils.MessageUtilities;
  57. import org.openspcoop2.message.xml.MessageXMLUtils;
  58. import org.openspcoop2.utils.NameValue;
  59. import org.openspcoop2.utils.Utilities;
  60. import org.openspcoop2.utils.transport.TransportRequestContext;
  61. import org.openspcoop2.utils.transport.http.HttpConstants;
  62. import org.openspcoop2.utils.xml.PrettyPrintXMLUtils;
  63. import org.slf4j.Logger;
  64. import org.w3c.dom.Element;
  65. import org.w3c.dom.Node;


  66. /**
  67.  * Libreria contenente metodi utili per la gestione della busta Soap.
  68.  *
  69.  *
  70.  * @author Poli Andrea (apoli@link.it)
  71.  * @author $Author$
  72.  * @version $Rev$, $Date$
  73.  */

  74. public class SoapUtils {

  75.     // SAX - TRANSFORMER
  76.    
  77.     public static  MessageException buildMessageException(String prefix, Throwable t) {
  78.         MessageException meSAXParser = null;
  79.         String msgSAXParser = null;
  80.         if(Utilities.existsInnerInstanceException(t, org.xml.sax.SAXParseException.class)) {
  81.             Throwable tExists = Utilities.getInnerInstanceException(t, org.xml.sax.SAXParseException.class, false);
  82.             if(tExists!=null) {
  83.                 msgSAXParser = tExists.getMessage();
  84.                 meSAXParser = new MessageException(prefix+tExists.getMessage(),t);
  85.             }
  86.         }
  87.        
  88.         // cerco TransformerException che contiene SAX Parser perchè almeno c'è anche l'indicazione sulla posizione dell'errore (riga e colonna)
  89.         if(msgSAXParser!=null && Utilities.existsInnerInstanceException(t, javax.xml.transform.TransformerException.class)) {
  90.             Throwable tExists = Utilities.getInnerInstanceException(t, javax.xml.transform.TransformerException.class, false);
  91.             if(tExists!=null && tExists.getMessage()!=null && tExists.getMessage().contains(msgSAXParser)) {
  92.                 return new MessageException(prefix+tExists.getMessage(),t);
  93.             }
  94.         }
  95.        
  96.         if(meSAXParser!=null) {
  97.             return meSAXParser;
  98.         }
  99.        
  100.         // Altrimenti cerco org.xml.sax.SAXException
  101.         MessageException meSAXException = null;
  102.         String msgSAXException = null;
  103.         if(Utilities.existsInnerInstanceException(t, org.xml.sax.SAXException.class)) {
  104.             Throwable tExists = Utilities.getInnerInstanceException(t, org.xml.sax.SAXException.class, false);
  105.             if(tExists!=null) {
  106.                 msgSAXException = tExists.getMessage();
  107.                 meSAXException = new MessageException(prefix+tExists.getMessage(),t);
  108.             }
  109.         }
  110.        
  111.         // cerco TransformerException che contiene SAX Exception perchè almeno c'è anche l'indicazione sulla posizione dell'errore (riga e colonna)
  112.         if(msgSAXException!=null && Utilities.existsInnerInstanceException(t, javax.xml.transform.TransformerException.class)) {
  113.             Throwable tExists = Utilities.getInnerInstanceException(t, javax.xml.transform.TransformerException.class, false);
  114.             if(tExists!=null && tExists.getMessage()!=null && tExists.getMessage().contains(msgSAXException)) {
  115.                 return new MessageException(prefix+tExists.getMessage(),t);
  116.             }
  117.         }
  118.        
  119.         if(meSAXException!=null) {
  120.             return meSAXException;
  121.         }
  122.        
  123.         return new MessageException(t.getMessage(),t);
  124.     }
  125.    
  126.    
  127.    
  128.     // SOAP FACTORY
  129.    
  130.     public static SOAPFactory getSoapFactory(OpenSPCoop2MessageFactory messageFactory, MessageType messageType) throws MessageNotSupportedException {
  131.         if(MessageType.SOAP_11.equals(messageType))
  132.             return messageFactory.getSoapFactory11();
  133.         else if(MessageType.SOAP_12.equals(messageType))
  134.             return messageFactory.getSoapFactory12();
  135.         else
  136.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  137.     }
  138.     public static MessageFactory getMessageFactory(OpenSPCoop2MessageFactory messageFactory) throws SOAPException {
  139.         return messageFactory.getSoapMessageFactory();
  140.     }
  141.        
  142.    
  143.     // SOAP Fault String 'Locale' for LANG
  144.    
  145.     private static Locale soapFaultStringLocale = null;
  146.     public static void setSoapFaultStringLocale(Locale soapFaultStringLocale) {
  147.         SoapUtils.soapFaultStringLocale = soapFaultStringLocale;
  148.     }
  149.     public static void setFaultString(SOAPFault fault, String faultString) throws SOAPException {
  150.          setFaultString(fault, faultString, null);
  151.     }
  152.     public static void setFaultString(SOAPFault fault, String faultString, Locale lParam) throws SOAPException {
  153.         if(lParam!=null) {
  154.             fault.setFaultString(faultString, lParam);
  155.         }
  156.         else if(soapFaultStringLocale!=null) {
  157.             fault.setFaultString(faultString, soapFaultStringLocale);
  158.         }
  159.         else {
  160.             fault.setFaultString(faultString);
  161.         }
  162.     }
  163.    
  164.    
  165.    
  166.    
  167.     // SOAP getElement
  168.    
  169.     public static SOAPElement getFirstSOAPElement(SOAPElement element) {
  170.         if(element!=null) {
  171.             Iterator<?> it = element.getChildElements();
  172.             while (it.hasNext()){
  173.                 Node tmp = (Node) it.next();
  174.                 if(tmp instanceof SOAPElement) {
  175.                     return (SOAPElement) tmp;
  176.                 }
  177.             }
  178.         }
  179.         return null;
  180.     }
  181.    
  182.    
  183.    
  184.    
  185.     // SOAP Content Type
  186.    
  187.     public static String getContentType(SOAPMessage msg) {
  188.         if(msg.getMimeHeaders()==null) {
  189.             return null;
  190.         }
  191.         String[] values = msg.getMimeHeaders().getHeader(HttpConstants.CONTENT_TYPE);
  192.         if (values == null || values.length<=0) {
  193.             return getContentType(msg.getMimeHeaders());
  194.         }
  195.         else {
  196.             return values[0];
  197.         }
  198.     }
  199.    
  200.     public static String getContentType(MimeHeaders mhs) {
  201.         if(mhs!=null) {
  202.             Iterator<MimeHeader> itMhs = mhs.getAllHeaders();
  203.             if(itMhs!=null) {
  204.                 while (itMhs.hasNext()) {
  205.                     MimeHeader mimeHeader = (MimeHeader) itMhs.next();
  206.                     if(mimeHeader!=null && mimeHeader.getName()!=null && HttpConstants.CONTENT_TYPE.toLowerCase().equals(mimeHeader.getName().toLowerCase())) {
  207.                         return mimeHeader.getValue();
  208.                     }
  209.                 }
  210.             }
  211.         }
  212.         return null;
  213.     }
  214.    
  215.    
  216.    
  217.    
  218.     // SOAPAction
  219.    
  220.     public static String getSoapAction(TransportRequestContext transportRequestContext, MessageType messageType, String contentType) throws MessageException, MessageNotSupportedException{

  221.         if(MessageType.SOAP_11.equals(messageType)){
  222.        
  223.             if(transportRequestContext.getHeaders()==null || transportRequestContext.getHeaders().size()<=0){
  224.                 throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' non valorizzato (nessun header di trasporto trovato)");
  225.             }
  226.            
  227.             Iterator<String> enTrasporto = transportRequestContext.getHeaders().keySet().iterator();
  228.             while(enTrasporto.hasNext()){
  229.                 String nomeProperty = (String)enTrasporto.next();
  230.                 if(Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION.equalsIgnoreCase(nomeProperty)){
  231.                     //System.out.println("TROVATO SOAP ACTION: "+req.getHeader(nomeProperty));
  232.                     String soapAction = transportRequestContext.getHeaderFirstValue(nomeProperty);
  233.                     if(soapAction==null){
  234.                         throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' non valorizzato (null)");
  235.                     }
  236.                     soapAction = soapAction.trim();
  237.                     if(soapAction.startsWith("\"")){
  238.                         if(!soapAction.endsWith("\"")){
  239.                             throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' non valorizzato correttamente (action quotata? Non è stato trovato il carattere di chiusura \" ma è presente quello di apertura)");
  240.                         }  
  241.                     }
  242.                     if(soapAction.endsWith("\"")){
  243.                         if(!soapAction.startsWith("\"")){
  244.                             throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' non valorizzato correttamente (action quotata? Non è stato trovato il carattere di apertura \" ma è presente quello di chiusura)");
  245.                         }  
  246.                     }
  247.                     return soapAction;
  248.                 }
  249.             }
  250.    
  251.             throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' non presente");
  252.            
  253.         }
  254.         else if(MessageType.SOAP_12.equals(messageType)){
  255.             // The SOAP 1.1 mandatory SOAPAction HTTP header has been removed in SOAP 1.2. In its place is an optional action parameter on the application/soap+xml media type.
  256.             ContentType ct = null;
  257.             try{
  258.                 ct = new ContentType(contentType);
  259.             }catch(Exception e){
  260.                 throw new MessageException("Content-Type '"+contentType+"' non valorizzato correttamente: "+e.getMessage(),e);
  261.             }
  262.             if(ct.getParameterList()!=null && ct.getParameterList().size()>0){
  263.                 Enumeration<?> names = ct.getParameterList().getNames();
  264.                 while (names.hasMoreElements()) {
  265.                     String name = (String) names.nextElement();
  266.                     if(Costanti.SOAP12_OPTIONAL_CONTENT_TYPE_PARAMETER_SOAP_ACTION.equals(name)){
  267.                         return ct.getParameterList().get(name);
  268.                     }  
  269.                 }
  270.             }
  271.            
  272.             return null;
  273.         }
  274.         else{
  275.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  276.         }
  277.        
  278.     }
  279.    
  280.     public static void checkSoapActionQuotedString(String soapAction,MessageType messageType) throws MessageException, MessageNotSupportedException{
  281.         if(MessageType.SOAP_11.equals(messageType)){
  282.             // WS-I BasicProfile 1.1: R1109   The value of the SOAPAction HTTP header field in a HTTP request MESSAGE MUST be a quoted string.
  283.             if(!soapAction.startsWith("\"") || !soapAction.endsWith("\"")){
  284.                 throw new MessageException("Header http '"+Costanti.SOAP11_MANDATORY_HEADER_HTTP_SOAP_ACTION+"' valorizzato tramite una stringa non quotata (WSI-BP-1.1 R1109)");
  285.             }
  286.         }
  287.         else{
  288.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  289.         }
  290.     }
  291.    
  292.    
  293.    
  294.    
  295.    
  296.     // SOAP HEADER E MUST UNDERSTAND
  297.    
  298.     public static String getSoapActor(SOAPHeaderElement headerElement, MessageType messageType) throws MessageNotSupportedException{
  299.        
  300.         if(MessageType.SOAP_11.equals(messageType)){
  301.             return headerElement.getActor();
  302.         }
  303.         else if(MessageType.SOAP_12.equals(messageType)){
  304.             return headerElement.getRole();
  305.         }
  306.         else{
  307.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  308.         }
  309.     }
  310.    
  311.     public static boolean checkMustUnderstandHeaderElement(MessageType messageType, SOAPHeader header,List<NameValue> filtri, StringBuilder bfErrorParam) throws MessageException {
  312.        
  313.        
  314.         StringBuilder bfError = new StringBuilder();
  315.         try{
  316.             java.util.Iterator<?> headers = header.getChildElements();
  317.             while (headers.hasNext()) {
  318.                 Object element = headers.next();
  319.                 if(!(element instanceof SOAPHeaderElement)){
  320.                     continue;
  321.                 }
  322.                
  323.                 SOAPHeaderElement elementHeader = (SOAPHeaderElement) element;
  324.                
  325.                 String actor = SoapUtils.getSoapActor(elementHeader, messageType);
  326.                
  327.                 // Prendo gli headers con MustUnderstand="1" senza Actor
  328.                 if(actor==null && elementHeader.getMustUnderstand()==true){
  329.                     boolean checked = false;
  330.                     if(filtri!=null && filtri.size()>0){
  331.                         for (NameValue nameValue : filtri) {
  332.                             String localName = nameValue.getName();
  333.                             String namespaceURI = nameValue.getValue();
  334.                             if(localName.equals(elementHeader.getLocalName()) && namespaceURI.equals(elementHeader.getNamespaceURI())){
  335.                                 // Ok si bypassa.
  336.                                 checked = true;
  337.                                 break;
  338.                             }
  339.                         }
  340.                     }
  341.                    
  342.                     // Controllo se abbiamo bypassato l'header
  343.                     if(!checked){
  344.                         // Abbiamo un MustUnderstand="1" senza Actor che non appare nella lista da Bypassare!

  345.                         if(bfError.length()>0){
  346.                             bfError.append(", ");
  347.                         }
  348.                         bfError.append("{").append(elementHeader.getNamespaceURI()).append("}").append(elementHeader.getLocalName());
  349.                        
  350.                     }
  351.                 }
  352.             }
  353.         }catch(java.lang.Exception e) {
  354.            
  355.             Throwable t = ParseExceptionUtils.getParseException(e);
  356.             if(t!=null){
  357.                 throw new MessageException(e);
  358.             }
  359.            
  360.             throw new MessageException("Riscontrato errore durante l'applicazione del bypassMustUnderstandHeader: "+e.getMessage(),e);
  361.         }  
  362.        
  363.         if(bfError.length()>0){
  364.             bfErrorParam.append(bfError.toString());
  365.         }
  366.         return bfError.length()<=0;
  367.     }
  368.    
  369.    
  370.    
  371.    
  372.     // SOAP With Attachments
  373.    
  374.     public static void addSWAStartParameterIfNotPresent(OpenSPCoop2Message message) throws MessageException {
  375.         addSWAStartParameterIfNotPresent(message, false, false);
  376.     }
  377.     public static void addSWAStartParameterIfNotPresent(OpenSPCoop2Message message, boolean addOnlyIfExistsContentIdRootPart) throws MessageException {
  378.         addSWAStartParameterIfNotPresent(message, addOnlyIfExistsContentIdRootPart, false);
  379.     }
  380.     public static void addSWAStartParameterIfNotPresent(OpenSPCoop2Message message, boolean addOnlyIfExistsContentIdRootPart, boolean forceAddStartParameter) throws MessageException {
  381.         if(message!=null && ServiceBinding.SOAP.equals(message.getServiceBinding())) {
  382.            
  383.             try {
  384.            
  385.                 OpenSPCoop2SoapMessage soapMsg = message.castAsSoap();
  386.                 if(!soapMsg.hasAttachments()) {
  387.                     return;
  388.                 }
  389.                 SOAPPart part = soapMsg.getSOAPPart();
  390.                 if(part==null) {
  391.                     throw new MessageException("SOAPPart is null?");
  392.                 }
  393.                
  394.                 String [] idOld = part.getMimeHeader(HttpConstants.CONTENT_ID);
  395.                 String id = null;
  396.                 if(idOld!=null && idOld.length>0) {
  397.                     id = idOld[0];
  398.                 }
  399.                 addSWAStartParameterIfNotPresentEngine(soapMsg, part,
  400.                         addOnlyIfExistsContentIdRootPart, forceAddStartParameter,
  401.                         id);
  402.                
  403.             }catch(Exception t) {
  404.                 throw new MessageException(t.getMessage(),t);
  405.             }
  406.            
  407.         }
  408.     }
  409.     private static void addSWAStartParameterIfNotPresentEngine(OpenSPCoop2SoapMessage soapMsg, SOAPPart part,
  410.             boolean addOnlyIfExistsContentIdRootPart, boolean forceAddStartParameter,
  411.             String id) throws MessageException, MessageNotSupportedException, ParseException {
  412.         /**System.out.println("=== SOAP id PART: "+id);*/
  413.         if(id==null) {
  414.             if(addOnlyIfExistsContentIdRootPart) {
  415.                 /**System.out.println("ContentId non esistente e creazione non richiesta");*/
  416.                 return;
  417.             }
  418.             id = soapMsg.createContentID("http://govway.org");
  419.             part.addMimeHeader("Content-Id", id);
  420.             /**System.out.println("=== ADD id PART ");*/
  421.         }
  422.         String cType = soapMsg.getContentType();
  423.         ContentType contentType = new ContentType(cType);
  424.         String startParam = contentType.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START);
  425.         /**System.out.println("startParam PART: "+startParam);*/
  426.         if(startParam==null || forceAddStartParameter) {
  427.             /**System.out.println("ADD START PARAM");*/
  428.             soapMsg.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START, id);
  429.         }
  430.     }
  431.    
  432.    
  433.    
  434.    
  435.     // GET NODES e ELEMENT
  436.    
  437.     public static List<Node> getNotEmptyChildNodes(OpenSPCoop2MessageFactory messageFactory, Node e){
  438.         return getNotEmptyChildNodes(messageFactory, e, true);
  439.     }
  440.     public static List<Node> getNotEmptyChildNodes(OpenSPCoop2MessageFactory messageFactory, Node e, boolean consideraTextNotEmptyAsNode){
  441.         return MessageXMLUtils.getInstance(messageFactory).getNotEmptyChildNodes(e, consideraTextNotEmptyAsNode);
  442.     }
  443.    
  444.     public static Node getFirstNotEmptyChildNode(OpenSPCoop2MessageFactory messageFactory, Node e){
  445.         return getFirstNotEmptyChildNode(messageFactory, e, true);
  446.     }
  447.     public static Node getFirstNotEmptyChildNode(OpenSPCoop2MessageFactory messageFactory, Node e, boolean consideraTextNotEmptyAsNode){
  448.         return MessageXMLUtils.getInstance(messageFactory).getFirstNotEmptyChildNode(e, consideraTextNotEmptyAsNode);
  449.     }
  450.    
  451.     public static List<SOAPElement> getNotEmptyChildSOAPElement(SOAPElement e){
  452.         List<SOAPElement> vec = new ArrayList<SOAPElement>();
  453.         Iterator<?> soapElements = e.getChildElements();
  454.         while (soapElements.hasNext()) {
  455.             Object soapElement = soapElements.next();
  456.             if(soapElement instanceof SOAPElement){
  457.                 vec.add((SOAPElement)soapElement);
  458.             }
  459.         }
  460.         return vec;
  461.     }
  462.    
  463.     public static SOAPElement getNotEmptyFirstChildSOAPElement(SOAPElement e){
  464.         Iterator<?> soapElements = e.getChildElements();
  465.         while (soapElements.hasNext()) {
  466.             Object soapElement = soapElements.next();
  467.             if(soapElement instanceof SOAPElement){
  468.                 return (SOAPElement)soapElement;
  469.             }
  470.         }
  471.         return null;
  472.     }

  473.    
  474.    
  475.     // VERSION, NAMESPACE e CONTENT-TYPE
  476.    
  477.     public static String getSoapEnvelopeNS(MessageType messageType) throws MessageNotSupportedException {
  478.         if(MessageType.SOAP_11.equals(messageType))
  479.             return Costanti.SOAP_ENVELOPE_NAMESPACE;
  480.         else if(MessageType.SOAP_12.equals(messageType))
  481.             return Costanti.SOAP12_ENVELOPE_NAMESPACE;
  482.         else
  483.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  484.     }
  485.    
  486.     public static String getSoapContentTypeForMessageWithoutAttachments(MessageType messageType) throws MessageNotSupportedException{
  487.         if(MessageType.SOAP_11.equals(messageType) || MessageType.SOAP_12.equals(messageType))
  488.             return MessageUtilities.getDefaultContentType(messageType);
  489.         else
  490.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  491.     }
  492.    
  493.     public static MessageType getSOAPVersion(Logger log, byte [] xml){
  494.         // La posizione dovrebbe garantirmi il giusto namespace
  495.         // Nel caso all'interno del body viene usato l'altro.
  496.         String s = new String(xml);
  497.         if( (s.contains("<Envelope") || s.contains(":Envelope") ) ){
  498.             int indexOfSoap11 = s.indexOf(Costanti.SOAP_ENVELOPE_NAMESPACE);
  499.             int indexOfSoap12 = s.indexOf(Costanti.SOAP12_ENVELOPE_NAMESPACE);
  500.             if(indexOfSoap11>0 && indexOfSoap12>0){
  501.                 if(indexOfSoap11<indexOfSoap12){
  502.                     return MessageType.SOAP_11;
  503.                 }
  504.                 else{
  505.                     return MessageType.SOAP_12;
  506.                 }
  507.             }
  508.             else if(indexOfSoap11>0){
  509.                 return MessageType.SOAP_11;
  510.             }
  511.             else if(indexOfSoap12>0){
  512.                 return MessageType.SOAP_12;
  513.             }
  514.         }
  515.         return null;
  516.     }
  517.    
  518.     public static boolean checkSOAPEnvelopeNamespace(OpenSPCoop2SoapMessage message, MessageType messageType) throws MessageException, MessageNotSupportedException{
  519.         try {
  520.             OpenSPCoop2MessageSoapStreamReader reader = message.getSoapReader();
  521.             String envelopeNamespace = null;
  522.             if(reader!=null) {
  523.                 envelopeNamespace = reader.getNamespace();
  524.             }
  525.             if(envelopeNamespace==null) {
  526.                 SOAPPart soapPart = message.getSOAPPart();
  527.                 if(soapPart!=null) {
  528.                     SOAPEnvelope envelope = soapPart.getEnvelope();
  529.                     if(envelope!=null) {
  530.                         envelopeNamespace = envelope.getNamespaceURI();
  531.                     }
  532.                 }
  533.             }
  534.            
  535.             if(envelopeNamespace==null && message instanceof AbstractOpenSPCoop2Message_soap_impl) {
  536.                 boolean hasContent = ((AbstractOpenSPCoop2Message_soap_impl<?>)message).hasContent();
  537.                 if(!hasContent) {
  538.                     throw new MessageException("Invalid empty message");
  539.                 }
  540.             }
  541.            
  542.             if(messageType.equals(MessageType.SOAP_11) &&  Costanti.SOAP_ENVELOPE_NAMESPACE.equals(envelopeNamespace)) {
  543.                 return true;
  544.             }
  545.            
  546.             if(messageType.equals(MessageType.SOAP_12) &&  Costanti.SOAP12_ENVELOPE_NAMESPACE.equals(envelopeNamespace)) {
  547.                 return true;
  548.             }
  549.            
  550.             return false;

  551.         } catch (Exception ex) {
  552.            
  553.             Throwable t = ParseExceptionUtils.getParseException(ex);
  554.             if(t!=null){
  555.                 throw new MessageException(ex);
  556.             }
  557.            
  558.             throw new MessageException(ex.getMessage(),ex);
  559.         }  
  560.     }

  561.    
  562.    
  563.     // NODE UTILS
  564.    
  565.     public static boolean matchLocalName(OpenSPCoop2MessageFactory messageFactory, Node nodo,String nodeName,String prefix,String namespace){
  566.         return MessageXMLUtils.getInstance(messageFactory).matchLocalName(nodo, nodeName, prefix, namespace);
  567.     }
  568.    
  569.     public static Node getAttributeNode(OpenSPCoop2MessageFactory messageFactory, Node node,String attributeName){
  570.         return MessageXMLUtils.getInstance(messageFactory).getAttributeNode(node, attributeName);
  571.     }
  572.     public static Node getQualifiedAttributeNode(OpenSPCoop2MessageFactory messageFactory, Node node,String attributeName,String namespace){
  573.         return MessageXMLUtils.getInstance(messageFactory).getQualifiedAttributeNode(node, attributeName, namespace);
  574.     }
  575.    
  576.    
  577.     // EQUALS
  578.    
  579.     public static void equalsSoapElements(SOAPElement element1,SOAPElement element2,boolean checkTextComment) throws MessageException{
  580.         try{
  581.             _equalsSoapElements(element1, element2, new ArrayList<>(),checkTextComment);
  582.         }catch(Exception e){
  583.             try{
  584.                 String soapReq = PrettyPrintXMLUtils.prettyPrintWithTrAX(element1);
  585.                 String soapRes = PrettyPrintXMLUtils.prettyPrintWithTrAX(element2);
  586.                 throw new MessageException("Element1 ["+soapReq+"] risulta differente da Element2 ["+soapRes+"] (motivo:"+e.getMessage()+")",e);
  587.             }catch(Exception eInternal){
  588.                 throw new MessageException(eInternal.getMessage(),eInternal);
  589.             }
  590.         }
  591.     }

  592.     private static String _getQualifiedName(QName attr){
  593.         if(attr.getNamespaceURI()!=null){
  594.             return "{"+ attr.getNamespaceURI()+" }"+attr.getLocalPart();
  595.         }
  596.         else{
  597.             return attr.getLocalPart();
  598.         }
  599.     }
  600.    
  601.     private static void _equalsSoapElements(SOAPElement el1,SOAPElement el2,List<String> namespacePrefixEl1,boolean checkTextComment) throws MessageException{
  602.        
  603.         /**************** controllo nome del nodo *****************************/
  604.         if(!el1.getNodeName().equals(el2.getNodeName())){
  605.             //System.out.println("NOME DIVERSO");
  606.             throw new MessageException("Node1 possiede un nome ["+el1.getNodeName()+"] differente dal nome del Node2 ["+el2.getNodeName()+"]");
  607.         }
  608.        
  609.        
  610.         Iterator<?> it=el1.getAllAttributesAsQNames();
  611.         Iterator<?> it2=el2.getAllAttributesAsQNames();
  612.         List <String>vet=new ArrayList<>();
  613.         List <String>vet2=new ArrayList<>();
  614.         /**************** controllo se gli attributi sono uguali*****************************/
  615.         while(it.hasNext()){
  616.             if(!it2.hasNext()){
  617.                 //System.out.println("ATTR 1");
  618.                 throw new MessageException("Node1 ["+el1.getNodeName()+"] possiede degli attributi, mentre nel node2 ["+el2.getNodeName()+"] non ve ne sono");
  619.             }
  620.             //Attributes att=(Attributes)it.next();
  621.             QName attr1 = ((QName) it.next());
  622.             vet.add( _getQualifiedName(attr1) );
  623.            
  624.             QName attr2 = ((QName) it2.next());
  625.             vet2.add( _getQualifiedName(attr2) );
  626.            
  627.         }
  628.         if(it2.hasNext()){
  629.             //System.out.println("ATTR 2");
  630.             throw new MessageException("Node2 ["+el2.getNodeName()+"] possiede piu' attributi del Node1 ["+el1.getNodeName()+"]");
  631.         }
  632.         if(!vet.containsAll(vet2)){
  633.             //System.out.println("ATTR 3");
  634.            
  635.             StringBuilder bfNode1 = new StringBuilder();
  636.             for (int i = 0; i < vet.size(); i++) {
  637.                 if(i>0){
  638.                     bfNode1.append(",");
  639.                 }
  640.                 bfNode1.append(vet.get(i));
  641.             }
  642.            
  643.             StringBuilder bfNode2 = new StringBuilder();
  644.             for (int i = 0; i < vet2.size(); i++) {
  645.                 if(i>0){
  646.                     bfNode2.append(",");
  647.                 }
  648.                 bfNode2.append(vet2.get(i));
  649.             }
  650.            
  651.             throw new MessageException("Node1 ["+el1.getNodeName()+"] e Node2 ["+el2.getNodeName()+"] non hanno gli stessi attributi. Attributi("+vet.size()+") di Node1: "+bfNode1+ " . Attributi("+vet2.size()+") di Node2: "+bfNode2);
  652.         }


  653.         for(int i=0;i<vet.size();i++){
  654.             String value=vet.get(i);
  655.             if(!el1.getAttribute(value).equals(el2.getAttribute(value))){
  656.                 throw new MessageException("L'attributo ["+value+"] di Node1 ["+el1.getNodeName()+"] possiede un valore ("+
  657.                             el1.getAttribute(value)+") differente dal valore presente nello stesso attributo nel Node2 ["+el2.getNodeName()+"] (valore:"+el2.getAttribute(value)+")");
  658.             }
  659.         }

  660.         /***************************** Namespace URI del nodo ********************************/
  661.         String str1=el1.getNamespaceURI();
  662.         String str2=el2.getNamespaceURI();
  663.        // System.out.println("el1 -- il namespace Uri del nodo e' "+str1);
  664.         //System.out.println("el2 -- il namespace Uri del nodo e' "+str2);
  665.         boolean namespaceIdentico = false;
  666.         if(str1!=null && str2!=null){
  667.             namespaceIdentico = str1.equals(str2);
  668.         }
  669.         else if(str1==null && str2==null){
  670.             namespaceIdentico = true;
  671.         }
  672.         if(!namespaceIdentico){
  673.             //System.out.println("URI");
  674.             throw new MessageException("Node1 ["+el1.getNodeName()+"] possiede un namespace ["+str1+"] differente dal namespace del Node2 ["+el2.getNodeName()+"] (namespace:"+str2+")");
  675.         }
  676.        
  677.        
  678.         /*****************************Controllo se i namespace sono uguali********************************/
  679.         Iterator<?> nameSp1=el1.getNamespacePrefixes();
  680.         Iterator<?> nameSp2=el2.getNamespacePrefixes();
  681.         List <String>nameSpVet1=new ArrayList<>();
  682.         List <String>nameSpVet2=new ArrayList<>();
  683.         String prefix1, prefix2, urlPrefix1, urlPrefix2;
  684.         while(nameSp1.hasNext() && nameSp2.hasNext())
  685.         {
  686.             prefix1=(String) nameSp1.next();
  687.             try{
  688.                 urlPrefix1 = el1.getNamespaceURI(prefix1);
  689.             }catch(Exception e){
  690.                 urlPrefix1 = el1.getNamespaceURI();
  691.             }
  692.             nameSpVet1.add(prefix1+"="+urlPrefix1);
  693.            
  694.             if(namespacePrefixEl1.contains((prefix1+"="+urlPrefix1))==false){
  695.                 //System.out.println("ADD COMPLESSIVO: "+prefix1+"="+urlPrefix1);
  696.                 namespacePrefixEl1.add(prefix1+"="+urlPrefix1);
  697.             }
  698.            
  699.             prefix2=(String) nameSp2.next();
  700.             try{
  701.                 urlPrefix2 = el2.getNamespaceURI(prefix2);
  702.             }catch(Exception e){
  703.                 urlPrefix2 = el2.getNamespaceURI();
  704.             }
  705.             nameSpVet2.add(prefix2+"="+urlPrefix2);            
  706.         }
  707.        
  708.         // Controllo uguaglianza
  709.         for(int i=0; i<nameSpVet1.size(); i++){
  710.             String n1 = (String) nameSpVet1.get(i);
  711.             boolean trovato = false;
  712.             for(int j=0; j<nameSpVet2.size(); j++){
  713.                 String n2 = (String) nameSpVet2.get(j);
  714.                 if(n1.equals(n2)){
  715.                     trovato = true;
  716.                     break;
  717.                 }          
  718.             }
  719.             if(trovato==false){
  720.                 // Cerco nei namespaces del padre
  721.                 if(namespacePrefixEl1.contains(n1)==false){
  722.                     //System.out.println("NON TROVATO: "+n1);
  723.                     throw new MessageException("Node1 ["+el1.getNodeName()+"] non contiene il prefix: "+n1);
  724.                 }
  725.             }
  726.         }
  727.        

  728.         if(!(nameSpVet1.size() == nameSpVet2.size())){
  729.             //System.out.println("SIZE NAMESPACE");
  730.            
  731.             StringBuilder bfNode1 = new StringBuilder();
  732.             for (int i = 0; i < nameSpVet1.size(); i++) {
  733.                 if(i>0){
  734.                     bfNode1.append(",");
  735.                 }
  736.                 bfNode1.append(nameSpVet1.get(i));
  737.             }
  738.            
  739.             StringBuilder bfNode2 = new StringBuilder();
  740.             for (int i = 0; i < nameSpVet2.size(); i++) {
  741.                 if(i>0){
  742.                     bfNode2.append(",");
  743.                 }
  744.                 bfNode2.append(nameSpVet2.get(i));
  745.             }
  746.            
  747.             throw new MessageException("Node1 ["+el1.getNodeName()+"] e Node2 ["+el2.getNodeName()+"] non hanno gli stessi prefix. Attributi("+nameSpVet1.size()+") di Node1: "+bfNode1+ " . Attributi("+nameSpVet2.size()+") di Node2: "+bfNode2);
  748.         }    
  749.        


  750.         /*****************chiamata ricorsiva per i figli********************/
  751.         Iterator<?> child=el1.getChildElements();
  752.         Iterator<?> child2=el2.getChildElements();
  753.         while(child.hasNext()){
  754.             if(checkTextComment){
  755.                 if(!child2.hasNext()){
  756.                     //System.out.println("CHILD1");
  757.                     throw new MessageException("Node2 ["+el2.getNodeName()+"] non ha child element, mentre il Node1 ["+el1.getNodeName()+"] ne possiede");
  758.                 }
  759.             }
  760.             Object obj=null;
  761.             if(child.hasNext())
  762.                 obj = child.next();
  763.            
  764.             Object obj2=null;
  765.             if(child2.hasNext())
  766.                 obj2=child2.next();
  767.            
  768.             if(checkTextComment==false){
  769.                
  770.                 while( (obj!=null) && (obj instanceof Text) ){
  771.                     if(child.hasNext()){
  772.                         obj=child.next();
  773.                     }
  774.                     else{
  775.                         obj=null;
  776.                     }
  777.                 }
  778.                
  779.                 while( (obj2!=null) && (obj2 instanceof Text) ){
  780.                     if(child2.hasNext()){
  781.                         obj2=child2.next();
  782.                     }
  783.                     else{
  784.                         obj2=null;
  785.                     }
  786.                 }
  787.            
  788.                 if(obj==null){
  789.                     if(obj2!=null){
  790.                         throw new MessageException("Node2 ["+el2.getNodeName()+"] possiede ulteriori child element ("+((SOAPElement)obj2).getNodeName()+") non presenti nel Node1 ["+el1.getNodeName()+"]");
  791.                     }
  792.                     else{
  793.                         break; // elementi terminati
  794.                     }
  795.                 }
  796.                 else{
  797.                     if(obj2==null){
  798.                         throw new MessageException("Node1 ["+el1.getNodeName()+"] possiede ulteriori child element ("+((SOAPElement)obj).getNodeName()+") non presenti nel Node2 ["+el2.getNodeName()+"]");
  799.                     }
  800.                 }
  801.             }
  802.            
  803.            
  804.             if (obj instanceof Text) {
  805.                 Text text = (Text) obj;
  806.                 if (!(obj2 instanceof Text)){
  807.                     //System.out.println("CHILD2");
  808.                     throw new MessageException("Node2 ["+el2.getNodeName()+"] non possiede l'element Text presente nel Node1 ["+el1.getNodeName()+"] (valore: "+text.toString()+")");
  809.                 }
  810.                 else{
  811.                     Text text2 = (Text) obj2;
  812.                     boolean value = text.toString().equals(text2.toString());
  813.                     //System.out.println("CHILD3 ["+value+"]");
  814.                     if(value==false){
  815.                         throw new MessageException("Node2 ["+el2.getNodeName()+"] possiede un element Text con valore ("+text2.toString()+") differente da quello presente nel Node1 ["+el1.getNodeName()+"] (valore:"+text.toString()+")");
  816.                     }
  817.                 }
  818.             }
  819.             else{
  820.                 if(obj2 instanceof Text){
  821.                     //System.out.println("CHILD4");
  822.                     throw new MessageException("Node2 ["+el2.getNodeName()+"] possiede un element Text ("+((Text)obj2).toString()+") non presente nel Node1 ["+el1.getNodeName()+"]");
  823.                 }
  824.                 @SuppressWarnings("unchecked")
  825.                 List<String> namespacePrefixEl1Parent = (List<String>) ((ArrayList<String>) namespacePrefixEl1).clone();
  826.                 _equalsSoapElements((SOAPElement)obj, (SOAPElement)obj2 , namespacePrefixEl1Parent,checkTextComment);
  827.             }
  828.         }


  829.     }
  830.    
  831.    
  832.    
  833.    



  834.     /* ********  FAULT  ******** */


  835.     public static String toString(OpenSPCoop2MessageFactory messageFactory, SOAPFault fault) throws MessageException{
  836.         return SoapUtils.toString(messageFactory, fault,true);
  837.     }
  838.    
  839.     public static String toString(OpenSPCoop2MessageFactory messageFactory, SOAPFault fault,boolean printDetails) throws MessageException{
  840.         return SoapUtils._toString(messageFactory, fault, true, true, null);
  841.     }
  842.    
  843.     public static String safe_toString(OpenSPCoop2MessageFactory messageFactory, SOAPFault fault, Logger log) throws MessageException{
  844.         return SoapUtils.safe_toString(messageFactory, fault, false, log);
  845.     }
  846.    
  847.     public static String safe_toString(OpenSPCoop2MessageFactory messageFactory, SOAPFault fault,boolean printDetails, Logger log) throws MessageException{
  848.         return SoapUtils._toString(messageFactory, fault, true, false, log);
  849.     }
  850.    
  851.     public static String _toString(OpenSPCoop2MessageFactory messageFactory, SOAPFault fault,boolean printDetails,
  852.             boolean throwsException, Logger log) throws MessageException{
  853.         try{
  854.             if(printDetails){
  855.                 if(fault!=null){
  856.                     return OpenSPCoop2MessageFactory.getAsString(messageFactory, fault,true);
  857.                 }else{
  858.                     return "SOAPFault non presente";
  859.                 }  
  860.             }
  861.             else{
  862.                 StringBuilder bf = new StringBuilder();
  863.                 if(fault!=null){
  864.                     bf.append("SOAPFault");
  865.                     try{
  866.                         if(fault.getFaultCode()!=null && !"".equals(fault.getFaultCode())){
  867.                             bf.append(" faultCode["+fault.getFaultCode()+"]");
  868.                         }
  869.                     } catch(Throwable e) {
  870.                         if(throwsException) {
  871.                             throw e;
  872.                         }
  873.                         bf.append(" faultCode[unparsable: "+e.getMessage()+"]");
  874.                     }
  875.                     try{
  876.                         if(fault.getFaultActor()!=null && !"".equals(fault.getFaultActor())){
  877.                             bf.append(" faultActor["+fault.getFaultActor()+"]");
  878.                         }
  879.                     } catch(Throwable e) {
  880.                         if(throwsException) {
  881.                             throw e;
  882.                         }
  883.                         bf.append(" faultActor[unparsable: "+e.getMessage()+"]");
  884.                     }
  885.                     try{
  886.                         if(fault.getFaultString()!=null && !"".equals(fault.getFaultString())){
  887.                             bf.append(" faultString["+fault.getFaultString()+"]");
  888.                         }
  889.                     } catch(Throwable e) {
  890.                         if(throwsException) {
  891.                             throw e;
  892.                         }
  893.                         bf.append(" faultString[unparsable: "+e.getMessage()+"]");
  894.                     }
  895.                    
  896.                 }else{
  897.                     return "SOAPFault non presente";
  898.                 }
  899.                
  900.                 return bf.toString();
  901.             }
  902.            
  903.         } catch(Throwable e) {
  904.             if(throwsException) {
  905.                 throw new MessageException("toString SOAPFault: "+e.getMessage(),e);
  906.             }
  907.             else {
  908.                 if(log!=null) {
  909.                     log.error("Unparsable SOAPFault: "+e.getMessage(),e);
  910.                 }
  911.                 return "Unparsable SOAPFault: "+e.getMessage();
  912.             }
  913.         }
  914.     }


  915.    
  916.    
  917.    
  918.    
  919.    
  920.    
  921.     /* ********  M E S S A G G I    F A U L T     S O A P    ******** */
  922.    
  923.     /**
  924.      * Metodo che si occupa di costruire un messaggio <code>SOAPFault</code>  con i seguenti campi :
  925.      * <p>
  926.      * <ul>
  927.      *   <li> FaultString : parametro <var>aFault</var>,
  928.      *   <li> FaultCode   : parametro <var>aCode</var>,
  929.      *   <li> FaultActor  : parametro <var>aActor</var>,
  930.      *   <li> <code>Detail</code> composto da tanti Detail quanto sono la lunghezza dei parametri seguenti :
  931.      *   <ul>
  932.      *       <li> LocalName : parametro <var>aDetailLocalName</var>,
  933.      *       <li> Prefix    : parametro <var>aDetailPrefix</var>,
  934.      *       <li> URI       : parametro <var>aDetailURI</var>,
  935.      *   </ul>
  936.      * </ul>
  937.      *
  938.      * @param aFault faultString del SOAPFault.
  939.      * @param aActor faultActor del SOAPFault.
  940.      * @param aCode  faultCode del SOAPFault.
  941.      * @param dettaglioEccezione Dettaglio dell'eccezione
  942.      * @return <tt>byte[]</tt> del messaggio Soap Fault costruito in caso di successo, <tt>null</tt> altrimenti.
  943.      *
  944.      */
  945.     public static byte[] build_Soap_Fault(OpenSPCoop2MessageFactory messageFactory, MessageType messageType, String aFault, String aActor, QName aCode,
  946.             Element dettaglioEccezione,boolean generaDetails) throws MessageException, MessageNotSupportedException  {

  947.         if(!MessageType.SOAP_11.equals(messageType) && !MessageType.SOAP_12.equals(messageType)){
  948.             throw MessageNotSupportedException.newMessageNotSupportedException(messageType);
  949.         }
  950.        
  951.         ByteArrayOutputStream byteMessaggio = null;
  952.         try{
  953.             OpenSPCoop2Message msg = messageFactory.createEmptyMessage(messageType,MessageRole.FAULT);
  954.             OpenSPCoop2SoapMessage soapMsg = msg.castAsSoap();
  955.             SOAPEnvelope env = (soapMsg.getSOAPPart()).getEnvelope();

  956.             //log.info("Setting SOAPBody with SOAPFault");
  957.             SOAPBody bdy = env.getBody();
  958.             bdy.addFault();
  959.             SOAPFault fault = bdy.getFault();

  960.             //log.info("Setting Fault");
  961.            
  962.             if(aFault != null)
  963.                 fault.setFaultString(aFault);
  964.             else
  965.                 fault.setFaultString("");

  966.             //log.info("Setting Fault Code");
  967.            
  968.             if(aCode != null)
  969.                 fault.setFaultCode(aCode);

  970.             //log.info("Setting Actor");
  971.             if(aActor != null)
  972.                 fault.setFaultActor(aActor);

  973.             //log.info("Setting Details");
  974.             if(generaDetails && dettaglioEccezione!=null){
  975.                 fault.addDetail();  
  976.                 Detail d = fault.getDetail();
  977.                 d.appendChild(d.getOwnerDocument().importNode(dettaglioEccezione,true));
  978.             }

  979.             //log.info("Build complete MessageSOAPFault");

  980.             // Return byte ....
  981.             byteMessaggio = new ByteArrayOutputStream();
  982.             msg.writeTo(byteMessaggio, true);
  983.             //log.info("-----Imbustamento------");
  984.             //log.info(byteMessaggio.toString());
  985.             //log.info("-----Imbustamento------");

  986.             byte [] risultato = byteMessaggio.toByteArray();
  987.             byteMessaggio.close();
  988.             return risultato;
  989.         } catch(Exception e) {
  990.             try{
  991.                 if(byteMessaggio!=null)
  992.                     byteMessaggio.close();
  993.             }catch(Exception eis){
  994.                 // close
  995.             }
  996.             throw new MessageException("Creazione MsgSOAPFault non riuscito: "+e.getMessage(),e);
  997.         }
  998.     }


  999. }