WSDLValidator.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.core.registry.wsdl;

  21. import java.io.ByteArrayOutputStream;
  22. import java.util.ArrayList;
  23. import java.util.List;

  24. import javax.xml.namespace.QName;
  25. import javax.xml.soap.SOAPBody;
  26. import javax.xml.soap.SOAPElement;
  27. import javax.xml.soap.SOAPEnvelope;

  28. import org.apache.commons.lang.StringUtils;
  29. import org.openspcoop2.core.registry.Message;
  30. import org.openspcoop2.core.registry.MessagePart;
  31. import org.openspcoop2.core.registry.Operation;
  32. import org.openspcoop2.core.registry.PortType;
  33. import org.openspcoop2.core.registry.constants.BindingStyle;
  34. import org.openspcoop2.core.registry.constants.BindingUse;
  35. import org.openspcoop2.core.registry.constants.CostantiRegistroServizi;
  36. import org.openspcoop2.core.registry.driver.DriverRegistroServiziException;
  37. import org.openspcoop2.core.registry.driver.IDAccordoFactory;
  38. import org.openspcoop2.message.MessageUtils;
  39. import org.openspcoop2.message.OpenSPCoop2Message;
  40. import org.openspcoop2.message.constants.MessageType;
  41. import org.openspcoop2.message.soap.SoapUtils;
  42. import org.openspcoop2.utils.UtilsException;
  43. import org.openspcoop2.utils.wsdl.WSDLException;
  44. import org.openspcoop2.utils.xml.AbstractValidatoreXSD;
  45. import org.openspcoop2.utils.xml.AbstractXMLUtils;
  46. import org.openspcoop2.utils.xml.ValidatoreXSD;
  47. import org.slf4j.Logger;
  48. import org.w3c.dom.Attr;
  49. import org.w3c.dom.Comment;
  50. import org.w3c.dom.Document;
  51. import org.w3c.dom.Element;
  52. import org.w3c.dom.NamedNodeMap;
  53. import org.w3c.dom.Node;
  54. import org.w3c.dom.Text;


  55. /**
  56.  * Classe utilizzata per validare i messaggi applicativi.
  57.  *
  58.  * @author Poli Andrea (apoli@link.it)
  59.  * @author Lezza Aldo (lezza@openspcoop.org)
  60.  * @author Lorenzo Nardi (nardi@link.it)
  61.  * @author $Author$
  62.  * @version $Rev$, $Date$
  63.  */

  64. public class WSDLValidator {

  65.     public static final String XMLSCHEMA_INSTANCE_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance";
  66.     public static final String XMLSCHEMA_INSTANCE_LOCAL_NAME_TYPE = "type";
  67.     private static final String PREFIX_RPC_AGGIUNTO = "op2RPC";
  68.    
  69.     /** OpenSPCoop2Message */
  70.     private OpenSPCoop2Message openspcoop2Message;
  71.     /** SOAPVersion */
  72.     private MessageType messageType;
  73.     /** Element */
  74.     private Element element;
  75.     /** WSDL Associato al servizio */
  76.     private AccordoServizioWrapper accordoServizioWrapper = null;
  77.     /** Logger */
  78.     private Logger logger = null;
  79.     /** XMLUtils */
  80.     private AbstractXMLUtils xmlUtils = null;
  81.    
  82.     /** Nodo xsiType Aggiunto */
  83.     private boolean gestioneXsiTypeRpcLiteral;
  84.     private SOAPElement rpcChildElement;
  85.     private QName rpcChildElementNamespaceAggiunto;
  86.     private QName rpcChildElementXSITypeAggiunto;
  87.    
  88.     /** Nodo rpc root element */
  89.     private boolean rpcAcceptRootElementUnqualified;
  90.    
  91.     /** XSI Type */
  92.     private boolean validationXsdAddNamespaceXSITypeIfNotExists;
  93.     private boolean validationRpcAddNamespaceXSITypeIfNotExists;
  94.     private boolean validationDocumentAddNamespaceXSITypeIfNotExists;

  95.     /** Prefix error */
  96.     private boolean addPrefixError = true;
  97.     public boolean isAddPrefixError() {
  98.         return this.addPrefixError;
  99.     }
  100.     public void setAddPrefixError(boolean addPrefixError) {
  101.         this.addPrefixError = addPrefixError;
  102.     }
  103.    
  104.     /* ------ Costruttore -------------- */
  105.     private static Element getEngineEnvelopeCatchException(OpenSPCoop2Message msg, boolean bufferMessageReadOnly, String idTransazione) throws WSDLException {
  106.         try {
  107.             boolean checkSoapBodyEmpty = true;
  108.             return MessageUtils.getContentElement(msg, checkSoapBodyEmpty, bufferMessageReadOnly, idTransazione);
  109.         }catch(Exception e){
  110.             throw new WSDLException(e.getMessage(),e);
  111.         }
  112.     }
  113.     public WSDLValidator(OpenSPCoop2Message msg,AbstractXMLUtils xmlUtils,AccordoServizioWrapper accordoServizioWrapper,Logger log,
  114.             WSDLValidatorConfig config, boolean addPrefixError,
  115.             boolean bufferMessageReadOnly, String idTransazione)throws WSDLException{
  116.         this(msg.getMessageType(), getEngineEnvelopeCatchException(msg,bufferMessageReadOnly,idTransazione), xmlUtils, accordoServizioWrapper, log,
  117.                 config, addPrefixError);
  118.         this.openspcoop2Message = msg;
  119.     }
  120.     // Il costruttore sottostante non puo' sfruttare la funzionalita' addNamespaceXSITypeIfNotExists
  121.     // per questo e' stato reso privato, poiche' tale funzionalita' richiede openspcoop2Message
  122.     private WSDLValidator(MessageType messageType, Element element,AbstractXMLUtils xmlUtils,AccordoServizioWrapper accordoServizioWrapper,Logger log,
  123.             WSDLValidatorConfig config, boolean addPrefixError)throws WSDLException{
  124.        
  125.         this.messageType = messageType;
  126.        
  127.         if(element==null){
  128.             throw new WSDLException("Contenuto da validatore non fornito");
  129.         }
  130.         this.element = element;
  131.         if(MessageType.SOAP_11.equals(this.messageType) || MessageType.SOAP_12.equals(this.messageType)){
  132.             SOAPEnvelope envelope = (SOAPEnvelope) element;
  133.             SOAPBody body = null;
  134.             try{
  135.                 body = envelope.getBody();
  136.             }catch(Exception e){
  137.                 if(this.logger!=null) {
  138.                     this.logger.error("SOAPEnvelope.getBody failed: "+e.getMessage(),e);
  139.                 }
  140.                 throw new WSDLException("SOAPEnvelope senza body");
  141.             }
  142.            
  143.             if(body==null || (body.hasChildNodes()==false)){
  144.                 throw new WSDLException("SOAPBody non esistente");
  145.             }
  146.         }
  147.        
  148.         this.logger = log;
  149.         this.xmlUtils = xmlUtils;
  150.         this.accordoServizioWrapper = accordoServizioWrapper;
  151.        
  152.         this.gestioneXsiTypeRpcLiteral = config.isGestioneXsiTypeRpcLiteral();
  153.        
  154.         this.rpcAcceptRootElementUnqualified = config.isRpcAcceptRootElementUnqualified();
  155.        
  156.         this.validationXsdAddNamespaceXSITypeIfNotExists = config.isValidationXsdAddNamespaceXSITypeIfNotExists();
  157.         this.validationRpcAddNamespaceXSITypeIfNotExists = config.isValidationRpcAddNamespaceXSITypeIfNotExists();
  158.         this.validationDocumentAddNamespaceXSITypeIfNotExists = config.isValidationDocumentAddNamespaceXSITypeIfNotExists();
  159.        
  160.         this.addPrefixError = addPrefixError;
  161.     }
  162.    
  163.    
  164.    
  165.    
  166.    
  167.    
  168.    
  169.     /* -------------- FINALIZE --------------------- */
  170.     public void wsdlConformanceCheck_restoreOriginalDocument(){
  171.         if(this.gestioneXsiTypeRpcLiteral && this.rpcChildElement!=null){
  172.             try{
  173.                 if(this.rpcChildElementXSITypeAggiunto!=null){
  174.                     this.rpcChildElement.removeAttribute(this.rpcChildElementXSITypeAggiunto);
  175.                 }
  176.             }catch(Exception e){
  177.                 this.logger.error("Errore durante l'eliminazione dell'attributo ["+this.rpcChildElementXSITypeAggiunto+"] dal rpc element");
  178.             }
  179.             try{
  180.                 if(this.rpcChildElementNamespaceAggiunto!=null){
  181.                     // alcune implementazioni usano l'uno o l'altro per eliminarlo
  182.                     this.rpcChildElement.removeAttribute(this.rpcChildElementNamespaceAggiunto);
  183.                     this.rpcChildElement.removeNamespaceDeclaration(PREFIX_RPC_AGGIUNTO);
  184.                 }
  185.             }catch(Exception e){
  186.                 this.logger.error("Errore durante l'eliminazione dell'attributo ["+this.rpcChildElementNamespaceAggiunto+"] dal rpc element");
  187.             }
  188.         }
  189.     }
  190.    
  191.    
  192.    
  193.    
  194.    
  195.    
  196.    
  197.     /* -------------- VALIDAZIONE XSD SENZA WSDL --------------------- */
  198.    
  199.     /**
  200.      * Validazione xsd
  201.      *
  202.      * @param isRichiesta Indicazione sul tipo di messaggio applicativo da gestire
  203.      * @throws WSDLException (contiene codice e msg di errore)
  204.      */
  205.     public void validateAgainstXSDSchema(boolean isRichiesta,String operationName) throws WSDLException,WSDLValidatorException{
  206.         this.validateAgainstXSDSchema(isRichiesta, operationName, this.ptWsdlConformanceCheck, this.opWsdlConformanceCheck);
  207.     }
  208.     public void validateAgainstXSDSchema(boolean isRichiesta,String operationName,PortType portType,Operation operation) throws WSDLException,WSDLValidatorException{

  209.         AbstractValidatoreXSD validatoreBodyApplicativo = null;
  210.         try{
  211.             if(this.accordoServizioWrapper.getSchema()!=null){
  212.                 validatoreBodyApplicativo = new ValidatoreXSD(this.accordoServizioWrapper.getSchema());
  213.             }else{
  214.                 throw new Exception("Schema non costruito?");
  215.             }
  216.         }catch(Exception e){
  217.             throw new WSDLException("Riscontrato errore durante la costruzione del validatore XSD per il contenuto applicativo: "+e.getMessage(),e);
  218.         }
  219.        
  220.        
  221.         /** ricerca ulteriore port type e operation in caso di validazione xsd */
  222.         if(portType==null && this.accordoServizioWrapper.getNomePortType()!=null){
  223.             // provo a cercarlo. Magari non e' stato fatto girare prima il metodo wsdlConformanceCheck
  224.             // o magari volutamente non c'e' un wsdl perche' la validazione prevista e' XSD
  225.             // in tal caso non e' un errore se il port type non e' presente.
  226.             portType = this.accordoServizioWrapper.getPortType(this.accordoServizioWrapper.getNomePortType());
  227.             if(portType==null){
  228.                 try{
  229.                     IDAccordoFactory idAccordoFactory = IDAccordoFactory.getInstance();
  230.                     String uriAccordo = idAccordoFactory.getUriFromIDAccordo(this.accordoServizioWrapper.getIdAccordoServizio());
  231.                     if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  232.                         this.logger.debug("Port-Type ["+this.accordoServizioWrapper.getNomePortType()+"] non esistente nei wsdl registrati all'interno dell'accordo di servizio "+uriAccordo);
  233.                     }else{
  234.                         this.logger.debug("Servizio ["+this.accordoServizioWrapper.getNomePortType()+"] non esistente nell'accordo di servizio "+uriAccordo);
  235.                     }
  236.                 }catch(Exception e){
  237.                     this.logger.error("Errore durante l'emissione del log che indica la non esistenza del porttype/servizio ["+this.accordoServizioWrapper.getNomePortType()+
  238.                             "] nei wsdl registrati all'interno dell'accordo di servizio: "+e.getMessage(),e);
  239.                 }
  240.             }
  241.         }
  242.         if(operation==null && operationName!=null && portType!=null){
  243.             // provo a cercare l'operation. Magari non e' stato fatto girare prima il metodo wsdlConformanceCheck
  244.             // o magari volutamente non c'e' un wsdl perche' la validazione prevista e' XSD
  245.             // in tal caso non e' un errore se l'operation non e' presente.
  246.             for(int i=0; i<portType.sizeAzioneList();i++){
  247.                 if(operationName.equals(portType.getAzione(i).getNome())){
  248.                     operation = portType.getAzione(i);
  249.                     break;
  250.                 }
  251.             }
  252.         }
  253.        
  254.        
  255.         StringBuilder errorMsgValidazioneXSD = new StringBuilder();
  256.        
  257.        
  258.         /** Validazione XSD senza considerare gli usi e gli stili (rpc/document e literal/encoded) */
  259.         if(portType==null || operation==null){
  260.             this.logger.debug("Validazione XSD senza considerare il WSDLAccordoServizio e quindi senza considerare style (document/rpc) e gli use (literal/encoded)");
  261.            
  262.             List<Node> nodeList = new ArrayList<Node>();
  263.             if(MessageType.SOAP_11.equals(this.messageType) || MessageType.SOAP_12.equals(this.messageType)){
  264.                 SOAPEnvelope envelope = (SOAPEnvelope) this.element;
  265.                 SOAPBody body = null;
  266.                 try{
  267.                     body = envelope.getBody();
  268.                 }catch(Exception e){
  269.                     // eccezione che non dovrebbe accadere. Lo stesso controllo viene fatto nel costruttore
  270.                     throw new RuntimeException(e.getMessage(),e);
  271.                 }
  272.                 org.w3c.dom.NodeList nl = body.getChildNodes();
  273.                 for(int i=0; i<nl.getLength(); i++){
  274.                     if ( (nl.item(i) instanceof Text) || (nl.item(i) instanceof Comment) ){
  275.                         continue;
  276.                     }
  277.                     nodeList.add(nl.item(i));
  278.                 }
  279.             }
  280.             else{
  281.                 nodeList.add(this.element);
  282.             }
  283.            
  284.             for(int i=0; i<nodeList.size(); i++){
  285.                 String nomeElemento = null;
  286.                 String namespaceElemento = null;
  287.                 Node n = null;
  288.                 try{
  289.                     n = nodeList.get(i);
  290.                     nomeElemento = n.getLocalName();
  291.                     namespaceElemento = n.getNamespaceURI();
  292.                    
  293.                     // Bug Fix: OPPT-784: Validazione fallisce in presenza di xsi:type e normalizzazione da axiom
  294.                     if(this.openspcoop2Message!=null && this.validationXsdAddNamespaceXSITypeIfNotExists) {
  295.                         this.openspcoop2Message.addNamespaceXSITypeIfNotExists(n, this.element);
  296.                     }
  297.                    
  298.                     validatoreBodyApplicativo.valida(n,true);
  299.                 }catch(Exception e){
  300.                     if(errorMsgValidazioneXSD.length()==0){
  301.                         if(this.addPrefixError) {
  302.                             if(isRichiesta) {
  303.                                 errorMsgValidazioneXSD.append("Request");
  304.                             }
  305.                             else {
  306.                                 errorMsgValidazioneXSD.append("Response");
  307.                             }
  308.                             errorMsgValidazioneXSD.append("content not conform to XSD specification\n");
  309.                         }
  310.                     }else{
  311.                         errorMsgValidazioneXSD.append("\n");
  312.                     }
  313.                     if(namespaceElemento!=null){
  314.                         nomeElemento = "{"+namespaceElemento+"}"+nomeElemento;
  315.                     }
  316.                     errorMsgValidazioneXSD.append("(element "+nomeElemento+") "+e.getMessage());
  317.                     String elementNonValidato = null;
  318.                     try{
  319.                         if(n!=null) {
  320.                             elementNonValidato = this.xmlUtils.toString(n);
  321.                         }
  322.                     }catch(Exception eString){
  323.                         this.logger.error("Errore durante la conversione del Node in String: "+eString.getMessage(),eString);
  324.                     }
  325.                     this.logger.error("Validazione fallita (elemento "+nomeElemento+") ["+elementNonValidato+"]: "+e.getMessage(),e);
  326.                 }
  327.             }
  328.         }
  329.        
  330.         /** Validazione XSD che considerare gli usi e gli stili (rpc/document e literal/encoded) */
  331.         else{
  332.             this.logger.debug("Validazione XSD che considera il WSDLAccordoServizio (ho localizzato prima il port-type:"+portType.getNome()+" e l'operation:"+operation.getNome()+")");
  333.             BindingStyle style = CostantiRegistroServizi.WSDL_STYLE_DOCUMENT;
  334.             BindingUse use = CostantiRegistroServizi.WSDL_USE_LITERAL;
  335.             String azione = operationName;
  336.            
  337.             try{
  338.    
  339.                 if(portType.getStyle()!=null && ("".equals(portType.getStyle().getValue())==false) &&
  340.                         CostantiRegistroServizi.WSDL_STYLE_RPC.equals(portType.getStyle()))
  341.                     style = CostantiRegistroServizi.WSDL_STYLE_RPC;
  342.                
  343.                 if(operation.getStyle()!=null && ("".equals(operation.getStyle().getValue())==false)){
  344.                     if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(operation.getStyle()))
  345.                         style = CostantiRegistroServizi.WSDL_STYLE_RPC;
  346.                     else if(CostantiRegistroServizi.WSDL_STYLE_DOCUMENT.equals(operation.getStyle()))
  347.                         style = CostantiRegistroServizi.WSDL_STYLE_DOCUMENT;
  348.                 }
  349.                
  350.             }catch(Exception e){
  351.                 if(errorMsgValidazioneXSD.length()>0){
  352.                     errorMsgValidazioneXSD.append("\n");
  353.                 }
  354.                 errorMsgValidazioneXSD.append("Error in recognizing wsdl style rpc/document '"+e.getMessage()+"'");
  355.                 this.logger.error("Validazione fallita durante il riconoscimento del wsdl style rpc/document: "+e.getMessage(),e);
  356.             }
  357.                
  358.             try{
  359.                 if(isRichiesta){
  360.                     if(operation.getMessageInput()!=null && operation.getMessageInput().getUse()!=null &&
  361.                             ("".equals(operation.getMessageInput().getUse().getValue())==false) &&
  362.                             CostantiRegistroServizi.WSDL_USE_ENCODED.equals(operation.getMessageInput().getUse()))
  363.                         use = CostantiRegistroServizi.WSDL_USE_ENCODED;
  364.                 }else{
  365.                     if(operation.getMessageOutput()!=null && operation.getMessageOutput().getUse()!=null &&
  366.                             ("".equals(operation.getMessageOutput().getUse().getValue())==false) &&
  367.                             CostantiRegistroServizi.WSDL_USE_ENCODED.equals(operation.getMessageOutput().getUse()))
  368.                         use = CostantiRegistroServizi.WSDL_USE_ENCODED;
  369.                 }

  370.             }catch(Exception e){
  371.                 if(errorMsgValidazioneXSD.length()>0){
  372.                     errorMsgValidazioneXSD.append("\n");
  373.                 }
  374.                 errorMsgValidazioneXSD.append("Error in recognizing wsdl use literal/encoded '"+e.getMessage()+"'");
  375.                 this.logger.error("Validazione fallita durante il riconoscimento del wsdl style literal/encoded: "+e.getMessage(),e);
  376.             }
  377.            
  378.             if(errorMsgValidazioneXSD.length()==0){
  379.                 this.logger.debug("Validazione XSD con style["+style+"] e use["+use+"]...");
  380.                
  381.                 List<Node> nodeList = new ArrayList<Node>();
  382.                 if(MessageType.SOAP_11.equals(this.messageType) || MessageType.SOAP_12.equals(this.messageType)){
  383.                     SOAPEnvelope envelope = (SOAPEnvelope) this.element;
  384.                     SOAPBody body = null;
  385.                     try{
  386.                         body = envelope.getBody();
  387.                     }catch(Exception e){
  388.                         // eccezione che non dovrebbe accadere. Lo stesso controllo viene fatto nel costruttore
  389.                         throw new RuntimeException(e.getMessage(),e);
  390.                     }
  391.                     org.w3c.dom.NodeList nl = body.getChildNodes();
  392.                     for(int i=0; i<nl.getLength(); i++){
  393.                         if ( (nl.item(i) instanceof Text) || (nl.item(i) instanceof Comment) ){
  394.                             continue;
  395.                         }
  396.                         nodeList.add(nl.item(i));
  397.                     }
  398.                 }
  399.                 else{
  400.                     nodeList.add(this.element);
  401.                 }
  402.                
  403.                 if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style)){
  404.                     int children=0;
  405.                     for(int i=0; i<nodeList.size(); i++){
  406.                         children++;
  407.                     }
  408.                    
  409.                     if(children>1){
  410.                         errorMsgValidazioneXSD.append("Operation '"+azione+"' (style RPC) bring more than one root element");
  411.                     }
  412.                 }

  413.                 if(errorMsgValidazioneXSD.length()==0){
  414.                     for(int i=0; i<nodeList.size(); i++){
  415.                         String nomeElemento = null;
  416.                         String namespaceElemento = null;
  417.                         Node n = null;
  418.                         Node nodo = null;
  419.                         Node nChild = null;
  420.                         try{
  421.                             n = nodeList.get(i);
  422.                             nomeElemento = n.getLocalName();
  423.                             namespaceElemento = n.getNamespaceURI();
  424.                             if(CostantiRegistroServizi.WSDL_USE_ENCODED.equals(use)){
  425.                                 this.logger.debug("Validazione XSD con style["+style+"] e use["+use+"], richiede la pulizia dei xsi:types prima della validazione...");
  426.                                 nodo = this.cleanXSITypes(n);
  427.                             }else{
  428.                                 nodo = n;
  429.                             }
  430.                                    
  431.                             if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style)){
  432.                                 this.logger.debug("Validazione XSD con style["+style+"] e use["+use+"] RPC Validation...");
  433.                                 String nomeAtteso = azione;
  434.                                 if(isRichiesta==false)
  435.                                     nomeAtteso = azione+"Response";
  436.                                 if(nomeAtteso.equals(nomeElemento)==false){
  437.                                     throw new Exception("Root element ["+nomeElemento+"] non equivale all'operation name "+nomeAtteso +" (RPC Style)");
  438.                                 }
  439.                                 // Valido figli
  440.                                 org.w3c.dom.NodeList nlChilds = nodo.getChildNodes();
  441.                                 this.logger.debug("Valido figli size: "+nlChilds.getLength());
  442.                                 for(int j=0; j<nlChilds.getLength(); j++){
  443.                                     //this.logger.debug("Tipo["+j+"]: "+nlChilds.item(j).getClass().getName());
  444.                                     //if (nlChilds.item(j) instanceof Text && ((Text) nlChilds.item(j)).getData().trim().length() == 0) { continue; }
  445.                                     if ( (nlChilds.item(j) instanceof Text) || (nlChilds.item(j) instanceof Comment) ){
  446.                                         continue;
  447.                                     }
  448.                                     nChild = nlChilds.item(j);
  449.                                    
  450.                                     // Bug Fix: OPPT-784: Validazione fallisce in presenza di xsi:type e normalizzazione da axiom
  451.                                     if(this.openspcoop2Message!=null && this.validationRpcAddNamespaceXSITypeIfNotExists) {
  452.                                         this.openspcoop2Message.addNamespaceXSITypeIfNotExists(nChild, this.element);
  453.                                     }
  454.                                    
  455.                                     validatoreBodyApplicativo.valida(nChild,true);
  456.                                 }
  457.                             }else{
  458.                                 this.logger.debug("Validazione XSD con style["+style+"] e use["+use+"] Document Validation...");
  459.                                
  460.                                 // Bug Fix: OPPT-784: Validazione fallisce in presenza di xsi:type e normalizzazione da axiom
  461.                                 if(this.openspcoop2Message!=null && this.validationDocumentAddNamespaceXSITypeIfNotExists) {
  462.                                     this.openspcoop2Message.addNamespaceXSITypeIfNotExists(nodo, this.element);
  463.                                 }
  464.                                
  465.                                 validatoreBodyApplicativo.valida(nodo,true);
  466.                             }
  467.                            
  468.                         }catch(Exception e){
  469.                             if(errorMsgValidazioneXSD.length()==0){
  470.                                 if(this.addPrefixError) {
  471.                                     if(isRichiesta) {
  472.                                         errorMsgValidazioneXSD.append("Request");
  473.                                     }
  474.                                     else {
  475.                                         errorMsgValidazioneXSD.append("Response");
  476.                                     }
  477.                                     errorMsgValidazioneXSD.append("content not conform to XSD specification\n");
  478.                                 }
  479.                             }else{
  480.                                 errorMsgValidazioneXSD.append("\n");
  481.                             }
  482.                             if(namespaceElemento!=null){
  483.                                 nomeElemento = "{"+namespaceElemento+"}"+nomeElemento;
  484.                             }
  485.                             errorMsgValidazioneXSD.append("(element "+nomeElemento+") "+e.getMessage());
  486.                            
  487.                             String elementNonValidato = null;
  488.                             try{
  489.                                 if(n!=null) {
  490.                                     elementNonValidato = this.xmlUtils.toString(n);
  491.                                 }
  492.                             }catch(Exception eString){
  493.                                 this.logger.error("Errore durante la conversione del Node in String: "+eString.getMessage(),eString);
  494.                             }
  495.                            
  496.                             String elementNonValidato_cleanXSIType = null;
  497.                             try{
  498.                                 if(nodo!=null) {
  499.                                     elementNonValidato_cleanXSIType = this.xmlUtils.toString(nodo);
  500.                                 }
  501.                             }catch(Exception eString){
  502.                                 this.logger.error("Errore durante la conversione del Node (clean xsiType) in String: "+eString.getMessage(),eString);
  503.                             }
  504.                            
  505.                             String elementNonValidato_child = null;
  506.                             try{
  507.                                 if(nChild!=null)
  508.                                     elementNonValidato_child = this.xmlUtils.toString(nChild);
  509.                             }catch(Exception eString){
  510.                                 this.logger.error("Errore durante la conversione del Node (clean xsiType) in String: "+eString.getMessage(),eString);
  511.                             }
  512.                            
  513.                             this.logger.error("Validazione fallita (elemento "+nomeElemento+") originale["+
  514.                                     elementNonValidato+"] cleanXsiType["+
  515.                                     elementNonValidato_cleanXSIType+"] nChild["+
  516.                                     elementNonValidato_child+"]: "+e.getMessage(),e);
  517.                         }
  518.                     }
  519.                 }
  520.             }
  521.         }
  522.         if(errorMsgValidazioneXSD.length()>0){
  523.             throw new WSDLValidatorException(errorMsgValidazioneXSD.toString());
  524.         }
  525.     }

  526.    
  527.    
  528.    
  529.    
  530.    
  531.    
  532.    
  533.    
  534.    
  535.    
  536.     /* -------------- VALIDAZIONE XSD CON WSDL --------------------- */
  537.    
  538.     /**
  539.      * Validazione WSDL
  540.      *
  541.      * @param isRichiesta Indicazione sul tipo di messaggio applicativo da gestire
  542.      *
  543.      */
  544.     private PortType ptWsdlConformanceCheck = null;
  545.     private Operation opWsdlConformanceCheck = null;
  546.     public PortType getPtWsdlConformanceCheck() {
  547.         return this.ptWsdlConformanceCheck;
  548.     }
  549.     public Operation getOpWsdlConformanceCheck() {
  550.         return this.opWsdlConformanceCheck;
  551.     }
  552. //  public void wsdlConformanceCheck(boolean isRichiesta,String soapAction,String operationName) throws WSDLValidatorException {
  553. //      this.wsdlConformanceCheck(isRichiesta, soapAction, operationName, true, false);
  554. //  }
  555.     public void wsdlConformanceCheck(boolean isRichiesta,String soapAction,String operationName,boolean throwSOAPActionException,boolean logErrorAsDebug) throws WSDLValidatorException {
  556.                
  557.         String portType = this.accordoServizioWrapper.getNomePortType();
  558.        
  559.         if(portType!=null){
  560.            
  561.             // l'accordo di servizio parte specifica e' stato collegato ad un port type nella parte comune.
  562.             // In tal caso uso la validazione ottimale rispetto al port type ed all'operation
  563.            
  564.             // l'azione busta deve essere obbligatoriamente presente.
  565.             if(operationName==null){
  566.                 throw new WSDLValidatorException("Operation name undefined");
  567.             }
  568.            
  569.             this.logger.info("WSDL, effettuo validazione wsdlConformanceCheck ottimale sia con port type che operation ...");
  570.             this._engineWsdlConformanceCheck(isRichiesta, soapAction, portType, operationName, throwSOAPActionException, logErrorAsDebug);
  571.            
  572.             // se la validazione ha avuto successo salvo il pt e l'operation
  573.             this.ptWsdlConformanceCheck = this.accordoServizioWrapper.getPortType(portType);
  574.             for(int i=0; i<this.ptWsdlConformanceCheck.sizeAzioneList(); i++){
  575.                 Operation operationAS = this.ptWsdlConformanceCheck.getAzione(i);
  576.                 if (operationAS.getNome().equals(operationName)) {
  577.                     this.opWsdlConformanceCheck = operationAS;
  578.                     break;
  579.                 }
  580.             }
  581.         }
  582.         else{
  583.            
  584.             // l'accordo di servizio parte specifica non e' stato collegato ad un port type nella parte comune.
  585.             // effettuo una validazione meno stringente.
  586.                
  587.             if(operationName!=null){
  588.                
  589.                 // *** cerco l'operation all'interno del wsdl. Se esiste una o piu' operation con tale nome, proviamo a validare il messaggio. ***
  590.                 this.logger.info("WSDL, effettuo validazione wsdlConformanceCheck cercando una qualche operation con nome ["+operationName+"]...");
  591.                 StringBuilder bfEccezione = new StringBuilder();
  592.                 boolean operationFound = _engineWsdlConformanceCheckAll(isRichiesta, soapAction, operationName, bfEccezione, throwSOAPActionException, logErrorAsDebug);
  593.                 if(operationFound){
  594.                     if(bfEccezione.length()>0){
  595.                         throw new WSDLValidatorException(bfEccezione.toString());
  596.                     }
  597.                     else{
  598.                         return;
  599.                     }
  600.                 }else{
  601.                     try{
  602.                         IDAccordoFactory idAccordoFactory = IDAccordoFactory.getInstance();
  603.                         String uriAccordo = idAccordoFactory.getUriFromIDAccordo(this.accordoServizioWrapper.getIdAccordoServizio());
  604.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  605.                             throw new WSDLValidatorException("Operation '"+operationName+"' undefined in the WSDL specification '"+uriAccordo+"'");
  606.                         }else{
  607.                             throw new WSDLValidatorException("Operation '"+operationName+"' undefined in the API specification '"+uriAccordo+"'");
  608.                         }
  609.                     }catch(DriverRegistroServiziException de){
  610.                         String msgErrore = "Errore durante la registrazione del messaggio di errore Operation ["+operationName+"] non trovata in alcun port-type esistente nei wsdl registrati all'interno dell'accordo di servizio";
  611.                         if(logErrorAsDebug){
  612.                             this.logger.debug(msgErrore);
  613.                         }else{
  614.                             this.logger.error(msgErrore,de);
  615.                         }
  616.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  617.                             throw new WSDLValidatorException("Operation '"+operationName+"' undefined in the WSDL specification");
  618.                         }else{
  619.                             throw new WSDLValidatorException("Operation '"+operationName+"' undefined in the API specification");
  620.                         }
  621.                     }
  622.                 }
  623.             }
  624.             else{
  625.            
  626.                 // ***
  627.                 //     non avendo trovato una azione che matchava con il nome dell'operation name,
  628.                 //     valido rispetto a tutti i messaggi possibili, rispettando pero' il ruolo tra richiesta e risposta
  629.                 //  ***    
  630.                 StringBuilder bfEccezione = new StringBuilder();
  631.                 this.logger.info("WSDL, effettuo validazione wsdlConformanceCheck utilizzando una qualunque operation ...");
  632.                 _engineWsdlConformanceCheckAll(isRichiesta, soapAction, null, bfEccezione, throwSOAPActionException, logErrorAsDebug);
  633.                 if(bfEccezione.length()>0){
  634.                     throw new WSDLValidatorException(bfEccezione.toString());
  635.                 }
  636.                 else{
  637.                     return;
  638.                 }
  639.                
  640.             }
  641.            
  642.         }
  643.        
  644.     }
  645.    
  646.     private boolean _engineWsdlConformanceCheckAll(boolean isRichiesta,String soapAction,String operationName, StringBuilder bfEccezione,boolean throwSOAPActionException,boolean logErrorAsDebug) throws WSDLValidatorException{
  647.        
  648.         try{
  649.        
  650.             IDAccordoFactory idAccordoFactory = IDAccordoFactory.getInstance();
  651.             String uriAccordo = idAccordoFactory.getUriFromIDAccordo(this.accordoServizioWrapper.getIdAccordoServizio());
  652.            
  653.             PortType [] pts = this.accordoServizioWrapper.getPortTypeList();
  654.             if(pts==null || pts.length<=0){
  655.                 if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  656.                     throw new WSDLValidatorException("PortTypes undefined in the WSDL specification '"+uriAccordo+"'");
  657.                 }else{
  658.                     throw new WSDLValidatorException("PortTypes undefined in the API specification '"+uriAccordo+"'");
  659.                 }
  660.             }
  661.             boolean operationFound = false;
  662.             for (int i = 0; i < pts.length; i++) {
  663.                 PortType pt = pts[i];
  664.                 List<Operation> ops = pt.getAzioneList();
  665.                 if(ops==null || ops.size()<=0){
  666.                     if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  667.                         throw new WSDLValidatorException("Operations undefined in PortType '"+pt.getNome()+"' of the WSDL specification '"+uriAccordo+"'");
  668.                     }else{
  669.                         throw new WSDLValidatorException("Operations undefined in Service '"+pt.getNome()+"' of the API specification '"+uriAccordo+"'");
  670.                     }
  671.                 }
  672.                 boolean validazioneCompletataConSuccesso = false;
  673.                 for (Operation operation : ops) {
  674.                    
  675.                     boolean verify = false;
  676.                     if(operationName==null){
  677.                         verify = true;
  678.                     }
  679.                     else{
  680.                         verify = (operation.getNome().equals(operationName));
  681.                         if(verify){
  682.                             operationFound = true;
  683.                         }
  684.                     }
  685.                    
  686.                     if(verify){
  687.                         try{
  688.                             this.logger.info("WSDL, effettuo validazione wsdlConformanceCheck per operation ["+operation.getNome()+"] del port type ["+pt.getNome()+"]...");
  689.                             this._engineWsdlConformanceCheck(isRichiesta, soapAction, pt.getNome(), operation.getNome(), throwSOAPActionException, logErrorAsDebug);
  690.                            
  691.                             // se la validazione ha avuto successo salvo il pt e l'operation
  692.                             this.ptWsdlConformanceCheck = pt;
  693.                             this.opWsdlConformanceCheck = operation;
  694.                            
  695.                             validazioneCompletataConSuccesso = true;
  696.                             break;
  697.                            
  698.                         }catch(WSDLValidatorException exception){
  699. //                          if(bfEccezione.length()>0){
  700.                             bfEccezione.append("\n");
  701.                             //}
  702.                             bfEccezione.append("[Tentativo validazione come PortType:").
  703.                                 append(pt.getNome()).
  704.                                 append(" Operation:").
  705.                                 append(operation.getNome()).
  706.                                 append(" fallito]: ").
  707.                                 append(exception.getMessage());
  708.                         }
  709.                     }
  710.                 }
  711.                
  712.                 if(validazioneCompletataConSuccesso){
  713.                     break;
  714.                 }
  715.             }
  716.            
  717.             return operationFound;
  718.            
  719.         }catch(WSDLValidatorException e){
  720.             throw e;
  721.         }catch(Exception e){
  722.             // Si entra in questo catch solo in caso di bug
  723.             String msgErrore = "Validazione WSDL ("+isRichiesta+") fallita: "+e.getMessage();
  724.             if(logErrorAsDebug){
  725.                 this.logger.debug(msgErrore);
  726.             }else{
  727.                 this.logger.error(msgErrore,e);
  728.             }
  729.             throw new WSDLValidatorException("WSDL Validation 'all-"+(isRichiesta?"request":"response")+"' failed: "+e.getMessage(),e);
  730.         }
  731.     }
  732.    
  733.     private void _engineWsdlConformanceCheck(boolean isRichiesta,String soapAction,String portType,String operation,boolean throwSOAPActionException,boolean logErrorAsDebug) throws WSDLValidatorException {
  734.        
  735.         String errorMsgValidazioneXSD = null;
  736.         try{
  737.            
  738.             SOAPEnvelope envelope = null;
  739.             SOAPBody body = null;
  740.             if(MessageType.SOAP_11.equals(this.messageType) || MessageType.SOAP_12.equals(this.messageType)){
  741.                 envelope = (SOAPEnvelope) this.element;
  742.                 try{
  743.                     body = envelope.getBody();
  744.                 }catch(Exception e){
  745.                     // eccezione che non dovrebbe accadere. Lo stesso controllo viene fatto nel costruttore
  746.                     throw new RuntimeException(e.getMessage(),e);
  747.                 }
  748.             }
  749.             else{
  750.                 throw new Exception("Tipo di validazione non supportata con Service Binding REST e tipologia messaggio: "+this.messageType.getMessageVersionAsString());
  751.             }
  752.            
  753.    
  754.             // cerco port-type
  755.             BindingStyle style = CostantiRegistroServizi.WSDL_STYLE_DOCUMENT;
  756.             BindingUse use = CostantiRegistroServizi.WSDL_USE_LITERAL;
  757.             String namespaceRPC = null;
  758.             Node rpcElement = null;
  759.             IDAccordoFactory idAccordoFactory = IDAccordoFactory.getInstance();
  760.             String uriAccordo = idAccordoFactory.getUriFromIDAccordo(this.accordoServizioWrapper.getIdAccordoServizio());
  761.             PortType portTypeAS = this.accordoServizioWrapper.getPortType(portType);
  762.             if(portTypeAS==null){
  763.                 if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  764.                     throw new WSDLValidatorException("PortType ["+portType+"] undefined in the WSDL specification '"+uriAccordo+"'");
  765.                 }else{
  766.                     throw new WSDLValidatorException("Service ["+portType+"] undefined in the API specification '"+uriAccordo+"'");
  767.                 }
  768.             }
  769.             if(portTypeAS.getStyle()!=null && ("".equals(portTypeAS.getStyle().getValue())==false) &&
  770.                     CostantiRegistroServizi.WSDL_STYLE_RPC.equals(portTypeAS.getStyle()))
  771.                 style = CostantiRegistroServizi.WSDL_STYLE_RPC;
  772.            
  773.             //si itera sulle operazioni del portType perche' potrebbe esserci
  774.             //overload di operazioni
  775.             if(portTypeAS.sizeAzioneList()<=0)
  776.                 throw new Exception("operations per il port type ["+portType+"] non presenti");
  777.             boolean matchingNameOperation = false, matchingArgomentsOperation = false;
  778.             String soapActionWSDL = null;
  779.             StringBuilder eccezioni = new StringBuilder();
  780.             StringBuilder eccezioneActionMatch = new StringBuilder();
  781.             for(int i=0; i<portTypeAS.sizeAzioneList(); i++){
  782.                 Operation operationAS = portTypeAS.getAzione(i);
  783.                 if (operationAS.getNome().equals(operation)) {
  784.                     matchingNameOperation = true;
  785.                     // Prendo la definizione del messaggio di input se e' una richiesta, di output se e' una risposta
  786.                     Message argumentsOperation = isRichiesta ? operationAS.getMessageInput() : operationAS.getMessageOutput();
  787.                    
  788.                     if(operationAS.getStyle()!=null && ("".equals(operationAS.getStyle().getValue())==false)){
  789.                         if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(operationAS.getStyle()))
  790.                             style = CostantiRegistroServizi.WSDL_STYLE_RPC;
  791.                         else if(CostantiRegistroServizi.WSDL_STYLE_DOCUMENT.equals(operationAS.getStyle()))
  792.                             style = CostantiRegistroServizi.WSDL_STYLE_DOCUMENT;
  793.                     }
  794.                    
  795.                     if(argumentsOperation!=null && argumentsOperation.getUse()!=null &&
  796.                             ("".equals(argumentsOperation.getUse().getValue())==false) &&
  797.                             CostantiRegistroServizi.WSDL_USE_ENCODED.equals(argumentsOperation.getUse()))
  798.                         use = CostantiRegistroServizi.WSDL_USE_ENCODED;
  799.                    
  800.                     if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style)){
  801.                         if(argumentsOperation!=null && argumentsOperation.getSoapNamespace()!=null &&
  802.                                 (!"".equals(argumentsOperation.getSoapNamespace()))){
  803.                             namespaceRPC = argumentsOperation.getSoapNamespace();
  804.                         }
  805.                     }
  806.                                        
  807.                     this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"] (RPCNamespace:"+namespaceRPC+") ...");
  808.                    
  809.                     // il controllo sul nome dell'operation non basta.
  810.                     // Vi puo' essere overriding del metodo per parametri diversi
  811.                     // controllo matching dei parametri
  812.                     org.w3c.dom.NodeList nodiContenutoApplicativo = null;
  813.                     Node nodoPossiedeContenutoApplicativo = null; // body nel caso document, rpc-element nel caso rpc
  814.                     if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style)){
  815.                         // RPC
  816.                         String nomeAtteso = operation;
  817.                         if(isRichiesta==false)
  818.                             nomeAtteso = operation+"Response";
  819.                         SOAPElement childRPCElement = SoapUtils.getNotEmptyFirstChildSOAPElement(body);
  820.                         if(childRPCElement==null){
  821.                             this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"]: Root element RCP non trovato rispetto all'operation name "+nomeAtteso +" (RPC Style)");
  822.                             continue;
  823.                         }
  824.                         if(nomeAtteso.equals(childRPCElement.getLocalName())==false){
  825.                             this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"]: Root element ["+childRPCElement.getLocalName()+"] non equivale all'operation name "+nomeAtteso +" (RPC Style)");
  826.                             continue;
  827.                         }
  828.                        
  829.                         nodiContenutoApplicativo = body.getChildNodes();
  830.                         for(int ii=0;ii<nodiContenutoApplicativo.getLength();ii++){
  831. //                          if (!(nodiContenutoApplicativo.item(ii) instanceof Text &&
  832. //                                  ((Text) nodiContenutoApplicativo.item(ii)).getData().trim().length() == 0)) {
  833.                             if (! ( (nodiContenutoApplicativo.item(ii) instanceof Text) || (nodiContenutoApplicativo.item(ii) instanceof Comment) )){
  834.                                 nodoPossiedeContenutoApplicativo = nodiContenutoApplicativo.item(ii);
  835.                                 rpcElement = nodoPossiedeContenutoApplicativo;
  836.                                 nodiContenutoApplicativo = nodoPossiedeContenutoApplicativo.getChildNodes();
  837.                                 break;
  838.                             }
  839.                         }
  840.                        
  841.                     }else{
  842.                         // Document
  843.                         nodiContenutoApplicativo = body.getChildNodes();
  844.                         nodoPossiedeContenutoApplicativo = body;
  845.                     }
  846.                    
  847.                     int sizeArgumentsOperation = 0;
  848.                     if(argumentsOperation!=null){
  849.                         sizeArgumentsOperation = argumentsOperation.sizePartList();
  850.                     }
  851.                     int nodiContenutoApplicativoLength = 0;
  852.                     StringBuilder nodiMessaggioErrore = new StringBuilder();
  853.                     for(int ii=0;ii<nodiContenutoApplicativo.getLength();ii++){
  854. //                      if (!(nodiContenutoApplicativo.item(ii) instanceof Text &&
  855. //                              ((Text) nodiContenutoApplicativo.item(ii)).getData().trim().length() == 0)) {
  856.                         if (! ( (nodiContenutoApplicativo.item(ii) instanceof Text) || (nodiContenutoApplicativo.item(ii) instanceof Comment) )){
  857.                            
  858.                             if(nodiMessaggioErrore.length()>0){
  859.                                 nodiMessaggioErrore.append(", ");
  860.                             }
  861.                             Node n = nodiContenutoApplicativo.item(ii);
  862.                             RootElementBody rootElementBody = new RootElementBody(envelope, nodoPossiedeContenutoApplicativo,
  863.                                     CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style), n);
  864.                             nodiMessaggioErrore.append(rootElementBody.toString());
  865.                            
  866.                             nodiContenutoApplicativoLength++;
  867.                             continue;
  868.                         }
  869.                     }
  870.                     if(sizeArgumentsOperation!=nodiContenutoApplicativoLength){
  871.                        
  872.                         if(eccezioneActionMatch.length()>0){
  873.                             eccezioneActionMatch.append("\n");
  874.                         }
  875.                         eccezioneActionMatch.append("Found "+nodiContenutoApplicativoLength+" parameter"+(nodiContenutoApplicativoLength>1?"s":"")+": ");
  876.                         eccezioneActionMatch.append(nodiMessaggioErrore.toString());
  877.                        
  878.                         this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"]: Argomenti attesi["+sizeArgumentsOperation+"], trovati nel body["+nodiContenutoApplicativo.getLength()+"]");
  879.                         continue;
  880.                     }
  881.                                        
  882.                     String tipo  = "output";
  883.                     if(isRichiesta)
  884.                         tipo = "input";
  885.                    
  886.                     if(argumentsOperation!=null && argumentsOperation.sizePartList()>0){
  887.                        
  888.                         // Mi conservo gli elementi presenti nel body
  889.                         List<RootElementBody> elementRootBody = new ArrayList<RootElementBody>();
  890.                         StringBuilder bodyElements = new StringBuilder();
  891.                         int numeroBodyElements = 0;
  892.                         int realIndexBody = 0;
  893.                         for(int indexBody = 0 ; indexBody<nodiContenutoApplicativo.getLength(); indexBody++){
  894. //                          if (nodiContenutoApplicativo.item(indexBody) instanceof Text &&
  895. //                                  ((Text) nodiContenutoApplicativo.item(indexBody)).getData().trim().length() == 0) {
  896.                             if ( (nodiContenutoApplicativo.item(indexBody) instanceof Text) || (nodiContenutoApplicativo.item(indexBody) instanceof Comment) ){
  897.                                 continue;
  898.                             }
  899.                            
  900.                             Node n = nodiContenutoApplicativo.item(indexBody);
  901.                            
  902.                             RootElementBody rootElementBody = new RootElementBody(envelope, nodoPossiedeContenutoApplicativo,
  903.                                     CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style), n);
  904.                             elementRootBody.add(rootElementBody);
  905.                            
  906.                             if(realIndexBody>0)
  907.                                 bodyElements.append(",");
  908.                             realIndexBody++;
  909.                             bodyElements.append(rootElementBody.toString());
  910.                         }
  911.                         numeroBodyElements = elementRootBody.size();
  912.                        
  913.                         int soapBodyArguments = nodiContenutoApplicativoLength;
  914.                         //per ogni tipo si itera
  915.                         int wsdlIndex=0;
  916.                         for( ; wsdlIndex<argumentsOperation.sizePartList(); wsdlIndex++){
  917.                             if (wsdlIndex == soapBodyArguments) {
  918.                                 //più oggetti definiti nel WSDL di quanti ce ne siano nel messaggio
  919.                                 this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"]: Più oggetti definiti nel WSDL di quanti ce ne siano nel messaggio");
  920.                                 continue;
  921.                             }
  922.                             MessagePart argument = argumentsOperation.getPart(wsdlIndex);
  923.                             String nomeElementAtteso = null;
  924.                             String namespaceElementAtteso = null;
  925.                             String tipoXSIAtteso = null;
  926.                             boolean validazioneTipologiaElement = (argument.getElementName()!=null);
  927.                             String argomentoAtteso = null;
  928.                             if(argument.getElementName()!=null){
  929.                                 nomeElementAtteso = argument.getElementName();
  930.                                 namespaceElementAtteso = argument.getElementNamespace();
  931.                             }
  932.                             else{
  933.                                 nomeElementAtteso = argument.getName(); // definito nel message del wsdl
  934.                                 namespaceElementAtteso = argument.getTypeNamespace();
  935.                                 tipoXSIAtteso = argument.getTypeName();
  936.                             }
  937.                             argomentoAtteso = RootElementBody.toString(nomeElementAtteso, namespaceElementAtteso, tipoXSIAtteso);
  938.                             boolean find = false;
  939.                             for(int indexBody = 0 ; indexBody<elementRootBody.size(); indexBody++){
  940.                                 RootElementBody r = elementRootBody.get(indexBody);
  941.                                 if(validazioneTipologiaElement){
  942.                                     if(nomeElementAtteso.equals(r.getLocalName()) && namespaceElementAtteso.equals(r.getNamespace())){
  943.                                         find = true;
  944.                                         elementRootBody.remove(indexBody);
  945.                                         continue;
  946.                                     }
  947.                                     else if(CostantiRegistroServizi.WSDL_USE_ENCODED.equals(use)){
  948.                                         if(nomeElementAtteso.equals(r.getLocalName()) && namespaceElementAtteso.equals(r.getNamespaceElementoCheContieneXSIType())){
  949.                                             find = true;
  950.                                             elementRootBody.remove(indexBody);
  951.                                             continue;
  952.                                         }
  953.                                     }
  954.                                 }
  955.                                 else{
  956.                                     if(nomeElementAtteso.equals(r.getLocalName()) &&
  957.                                             namespaceElementAtteso.equals(r.getNamespace()) &&
  958.                                             tipoXSIAtteso.equals(r.getXsiType())){
  959.                                         find = true;
  960.                                         elementRootBody.remove(indexBody);
  961.                                         continue;
  962.                                     }
  963.                                 }
  964.                             }
  965.    
  966.                             if (!find) { //tipi non concordi nella sequenza
  967.                                 boolean error = true;
  968.                                 if(CostantiRegistroServizi.WSDL_STYLE_RPC.equals(style) && CostantiRegistroServizi.WSDL_USE_LITERAL.equals(use) &&
  969.                                         tipoXSIAtteso!=null &&
  970.                                         elementRootBody.size()==1 && // elementi nel body sono uno
  971.                                         argumentsOperation.sizePartList()==1 // elementi attesi nel wsdl uno
  972.                                         ){
  973.                                    
  974.                                     SOAPElement rpcOperation = SoapUtils.getNotEmptyFirstChildSOAPElement(body);
  975.                                     if(rpcOperation!=null){
  976.                                         SOAPElement childRpc = SoapUtils.getNotEmptyFirstChildSOAPElement(rpcOperation);
  977.                                         if(this.gestioneXsiTypeRpcLiteral &&
  978.                                                 childRpc!=null && nomeElementAtteso!=null && nomeElementAtteso.equals(childRpc.getLocalName())){
  979.                                             try{
  980. //                                              System.out.println("PRIMA: "+org.openspcoop2.message.OpenSPCoop2MessageFactory.getMessageFactory().createEmptySOAPMessage(SOAPVersion.SOAP11).
  981. //                                                      getAsString(childRpc, false));
  982.                                                
  983.                                                 QName namespaceId = new QName("xmlns:"+PREFIX_RPC_AGGIUNTO);
  984.                                                 childRpc.addAttribute(namespaceId, namespaceElementAtteso);
  985.                                                 this.rpcChildElementNamespaceAggiunto = namespaceId;
  986.                                            
  987.                                                 QName id = new QName(XMLSCHEMA_INSTANCE_NAMESPACE,XMLSCHEMA_INSTANCE_LOCAL_NAME_TYPE,"xsi");
  988.                                                 String value = PREFIX_RPC_AGGIUNTO+":"+tipoXSIAtteso;
  989.                                                 childRpc.addAttribute(id, value);
  990.                                                 this.rpcChildElementXSITypeAggiunto = id;
  991.                                            
  992. //                                              System.out.println("DOPO: "+org.openspcoop2.message.OpenSPCoop2MessageFactory.getMessageFactory().createEmptySOAPMessage(SOAPVersion.SOAP11).
  993. //                                                      getAsString(childRpc, false));
  994.                                                 error= false;
  995.                                                 this.rpcChildElement = childRpc;
  996.                                             }catch(Exception e){
  997.                                                 this.logger.error("Errore durante la registrazione degli attributi richiesti per la validazione rpc con type: "+e.getMessage(),e);
  998.                                                 try{
  999.                                                     if(this.rpcChildElementNamespaceAggiunto!=null){
  1000.                                                         // ripulisco
  1001.                                                         // alcune implementazioni usano l'uno o l'altro per eliminarlo
  1002.                                                         this.rpcChildElement.removeAttribute(this.rpcChildElementNamespaceAggiunto);
  1003.                                                         this.rpcChildElement.removeNamespaceDeclaration(PREFIX_RPC_AGGIUNTO);
  1004.                                                     }
  1005.                                                 }catch(Exception eClose){
  1006.                                                     // ignore
  1007.                                                 }
  1008.                                             }
  1009.                                         }
  1010.                                     }
  1011.                                 }
  1012.                                 if(error){
  1013.                                     eccezioni.append("\nRequired "+tipo+" parameter '"+argomentoAtteso+"' undefined in "+numeroBodyElements+" body root-element("+(numeroBodyElements>1?"s":"")+") founded: "+bodyElements);
  1014.                                     this.logger.debug("WSDL, esamino operation["+operation+"] con style["+style+"] e use["+use+"]: Atteso "+argomentoAtteso+" body "+bodyElements);
  1015.                                     break;
  1016.                                 }
  1017.                             }
  1018.                         }
  1019.                         if (wsdlIndex == soapBodyArguments) {
  1020.                             soapActionWSDL = operationAS.getSoapAction();
  1021.                             matchingArgomentsOperation = true;
  1022.                             continue;
  1023.                         }
  1024.                     }

  1025.                 } //fine if
  1026.             }

  1027.             if (!matchingArgomentsOperation) {
  1028.                 if (matchingNameOperation) {
  1029.                     if(eccezioni.length()>0){
  1030.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1031.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+", style:"+style+", use:"+use+"): "+eccezioni.toString());
  1032.                         }else{
  1033.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+", style:"+style+", use:"+use+"): "+eccezioni.toString());
  1034.                         }
  1035.                     }
  1036.                     else if(eccezioneActionMatch.length()>0){
  1037.                         StringBuilder bfMessage = new StringBuilder();
  1038.                         for(int i=0; i<portTypeAS.sizeAzioneList(); i++){
  1039.                             Operation operationAS = portTypeAS.getAzione(i);
  1040.                             if (operationAS.getNome().equals(operation)) {
  1041.                                 Message argumentsOperation = isRichiesta ? operationAS.getMessageInput() : operationAS.getMessageOutput();
  1042.                                 int length = 0;
  1043.                                 if(argumentsOperation!=null && argumentsOperation.getPartList()!=null){
  1044.                                     length = argumentsOperation.getPartList().size();
  1045.                                 }
  1046.                                 bfMessage.append("\n");
  1047.                                 bfMessage.append("Expected "+length+" parameter"+(length>1?"s":"")+": ");
  1048.                                 if(length>0){
  1049.                                     for (int j = 0; j < length; j++) {
  1050.                                         MessagePart argument = argumentsOperation.getPart(j);
  1051.                                         String nomeElementAtteso = null;
  1052.                                         String namespaceElementAtteso = null;
  1053.                                         String tipoXSIAtteso = null;
  1054.                                         String argomentoAtteso = null;
  1055.                                         if(argument.getElementName()!=null){
  1056.                                             nomeElementAtteso = argument.getElementName();
  1057.                                             namespaceElementAtteso = argument.getElementNamespace();
  1058.                                         }
  1059.                                         else{
  1060.                                             nomeElementAtteso = argument.getName(); // definito nel message del wsdl
  1061.                                             namespaceElementAtteso = argument.getTypeNamespace();
  1062.                                             tipoXSIAtteso = argument.getTypeName();
  1063.                                         }
  1064.                                         argomentoAtteso = RootElementBody.toString(nomeElementAtteso, namespaceElementAtteso, tipoXSIAtteso);
  1065.                                         if(j>0){
  1066.                                             bfMessage.append(", ");
  1067.                                         }
  1068.                                         bfMessage.append(argomentoAtteso);
  1069.                                     }
  1070.                                 }
  1071.                             }
  1072.                         }
  1073.                         bfMessage.append("\n").append(eccezioneActionMatch.toString());

  1074.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1075.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+", style:"+style+", use:"+use+"): "+bfMessage.toString());
  1076.                         }else{
  1077.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+", style:"+style+", use:"+use+"): "+bfMessage.toString());
  1078.                         }

  1079.                     }
  1080.                     else{
  1081.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1082.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+", style:"+style+", use:"+use+")");
  1083.                         }else{
  1084.                             throw new WSDLValidatorException("Invalid "+(isRichiesta?"request":"response")+" by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+", style:"+style+", use:"+use+")");
  1085.                         }
  1086.                     }
  1087.                 } else {
  1088.                     if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1089.                         throw new WSDLValidatorException("Operation '"+operation+"' undefined in PortType '"+portType+"' of the WSDL specification '"+uriAccordo+"'");
  1090.                     }else{
  1091.                         throw new WSDLValidatorException("Operation '"+operation+"' undefined in Service '"+portType+"' of the API specification '"+uriAccordo+"'");
  1092.                     }
  1093.                 }
  1094.             }
  1095.            
  1096.             if( isRichiesta && soapActionWSDL!=null){
  1097.                 this.logger.debug("CheckSOAPAction");
  1098.                 String soapActionRipulita = null;
  1099.                 if(soapAction!=null){
  1100.                     soapActionRipulita = soapAction.trim();
  1101.                     if(soapActionRipulita.startsWith("\"")){
  1102.                         soapActionRipulita = soapActionRipulita.substring(1);
  1103.                     }
  1104.                     if(soapActionRipulita.endsWith("\"")){
  1105.                         soapActionRipulita = soapActionRipulita.substring(0,(soapActionRipulita.length()-1));
  1106.                     }
  1107.                 }
  1108.                 if(soapActionWSDL.equalsIgnoreCase(soapActionRipulita)==false){
  1109.                     boolean tmpThrowSOAPActionException = throwSOAPActionException;
  1110.                     if(soapActionRipulita==null && MessageType.SOAP_12.equals(this.messageType)){
  1111.                         // 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.
  1112.                         // Quindi se nella richiesta non era presente una soapAction, non devo sollevare eccezione
  1113.                         tmpThrowSOAPActionException = false;
  1114.                     }
  1115.                     // Validazione SOAPAction
  1116.                     if(tmpThrowSOAPActionException){
  1117.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1118.                             throw new WSDLValidatorException("Invalid soap action '"+soapActionRipulita+"' by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+", soap action:"+soapActionWSDL+")");
  1119.                         }else{
  1120.                             throw new WSDLValidatorException("Invalid soap action '"+soapActionRipulita+"' by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+", soap action:"+soapActionWSDL+")");
  1121.                         }
  1122.                     }
  1123.                 }
  1124.             }
  1125.            
  1126.             // Controllo sul namespace RPC.
  1127.             if(namespaceRPC!=null && rpcElement!=null){
  1128.                 this.logger.debug("CheckRPCNamespace");
  1129.                
  1130.                 if( (rpcElement.getNamespaceURI()==null || StringUtils.isEmpty(rpcElement.getNamespaceURI())) ){
  1131.                     if(!this.rpcAcceptRootElementUnqualified) {
  1132.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1133.                             throw new WSDLValidatorException("Unqualified rpc "+(isRichiesta?"request":"response")+" element '"+rpcElement.getLocalName()+"' by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+")");
  1134.                         }else{
  1135.                             throw new WSDLValidatorException("Unqualified rpc "+(isRichiesta?"request":"response")+" element '"+rpcElement.getLocalName()+"' by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+")");
  1136.                         }
  1137.                     }
  1138.                 }
  1139.                 else {
  1140.                     if(!rpcElement.getNamespaceURI().equals(namespaceRPC)){
  1141.                         if(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()){
  1142.                             throw new WSDLValidatorException("Invalid rpc "+(isRichiesta?"request":"response")+" element '"+rpcElement.getLocalName()+"' by WSDL specification '"+uriAccordo+"' (port-type:"+portType+", operation:"+operation+"): expected namespace '"+namespaceRPC+"'; found namespace '"+rpcElement.getNamespaceURI()+"'");
  1143.                         }else{
  1144.                             throw new WSDLValidatorException("Invalid rpc "+(isRichiesta?"request":"response")+" element '"+rpcElement.getLocalName()+"' by API specification '"+uriAccordo+"' (service:"+portType+", operation:"+operation+"): expected namespace '"+namespaceRPC+"'; found namespace '"+rpcElement.getNamespaceURI()+"'");
  1145.                         }
  1146.                     }
  1147.                 }
  1148.             }
  1149.            
  1150.         }catch(Exception e){
  1151.             String msgErrore = "Validazione WSDL ("+isRichiesta+") fallita: "+e.getMessage();
  1152.             if(logErrorAsDebug){
  1153.                 this.logger.debug(msgErrore);
  1154.             }else{
  1155.                 this.logger.error(msgErrore,e);
  1156.             }
  1157.             if( (e instanceof WSDLValidatorException)==false )
  1158.                 this.logger.debug("Validazione WSDL fallita",e);
  1159.             // è gia nella definizione dell'error
  1160.             StringBuilder errorMsgValidazioneXSDBuilder = new StringBuilder();
  1161.             if(this.addPrefixError) {
  1162.                 if(isRichiesta) {
  1163.                     errorMsgValidazioneXSDBuilder.append("Request");
  1164.                 }
  1165.                 else {
  1166.                     errorMsgValidazioneXSDBuilder.append("Response");
  1167.                 }
  1168.                 errorMsgValidazioneXSDBuilder.append(" content not conform to ").append(this.accordoServizioWrapper.isPortTypesLoadedFromWSDL()?"WSDL":"API").append(" specification; ");
  1169.             }
  1170.             errorMsgValidazioneXSDBuilder.append(e.getMessage());
  1171.             errorMsgValidazioneXSD = errorMsgValidazioneXSDBuilder.toString();
  1172.         }
  1173.         if(errorMsgValidazioneXSD!=null){
  1174.             throw new WSDLValidatorException(errorMsgValidazioneXSD);
  1175.         }
  1176.        
  1177.     }
  1178.    
  1179.    
  1180.    
  1181.    
  1182.    
  1183.    
  1184.    
  1185.    
  1186.    
  1187.     /* -------------- VALIDAZIONE UTILITIES --------------------- */
  1188.    
  1189.     public Element cleanXSITypes(Node node) throws Exception{
  1190.        
  1191.         //La versione non e' rilevante.
  1192.         byte[] element = this.eraserType (this.xmlUtils.toByteArray(node,true));
  1193.         Document doc = this.xmlUtils.newDocument(element);
  1194.         Element domElem = doc.getDocumentElement();
  1195.        
  1196.         /*  vecchia impl:
  1197.         MessageElement daClonare = (MessageElement) node;
  1198.         //System.out.println("PRIMA ["+daClonare.getAsString()+"] ");
  1199.         byte[]element = this.eraserType(daClonare.getAsString().getBytes());
  1200.         //System.out.println("DOPO ["+new String(element)+"] ");
  1201.         Element e =  XMLUtils.newElement(element);
  1202.         */
  1203.        
  1204.         return domElem;
  1205.     }
  1206.     /**
  1207.      * Metodo che si occupa di effettuare l'eliminazione degli xsd:type String
  1208.      *
  1209.      * utility che elimina gli xsd type
  1210.      * @param xml Xml su cui effettuare la pulizia dell'header.
  1211.      * @return byte[] contenente un xml 'pulito'.
  1212.      *
  1213.      */
  1214.     public byte[] eraserType(byte[] xml) throws UtilsException{

  1215.         ByteArrayOutputStream cleanXML = null;
  1216.         String prefix = "";
  1217.         try{
  1218.             cleanXML = new ByteArrayOutputStream();

  1219.             // Elimino import
  1220.             for(int i=0; i<xml.length ; ){

  1221.                 if(xml[i] == ' '){

  1222.                     // Cerco Stringa  " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
  1223.                     String importXSITYPE = "http://www.w3.org/2001/XMLSchema-instance";
  1224.                     if(i+"xmlns:".length() < xml.length){
  1225.                         if( (xml[i+1] == 'x') &&
  1226.                             (xml[i+2] == 'm') &&
  1227.                             (xml[i+3] == 'l') &&
  1228.                             (xml[i+4] == 'n') &&
  1229.                             (xml[i+5] == 's') &&
  1230.                             (xml[i+6] == ':')){
  1231.                             StringBuilder test = new StringBuilder("xmlns:");
  1232.                             StringBuilder prefixTest = new StringBuilder();
  1233.                             int contatoreFineAttributo = 0;
  1234.                             for(int k=7 ; ; k++){
  1235.                                 if((i+k)>=xml.length)
  1236.                                     break;
  1237.                                 if((char)xml[i+k] == '"')
  1238.                                     contatoreFineAttributo++;
  1239.                                 if(contatoreFineAttributo==0)
  1240.                                     prefixTest.append((char)xml[i+k]);
  1241.                                 test.append((char)xml[i+k]);
  1242.                                 if(contatoreFineAttributo>=2)
  1243.                                     break;
  1244.                             }
  1245.                             //System.out.println("TROVATO ["+test.toString()+"] PREFIX["+prefixTest.toString()+"]");
  1246.                             // Prelevo valore
  1247.                             int indexFirst = test.toString().indexOf('"');
  1248.                             int secondFirst = test.toString().indexOf('"', indexFirst+1);
  1249.                             String testEquals = test.toString().substring(indexFirst+1, secondFirst);
  1250.                             //System.out.println("TROVATO SUBSTRING ["+testEquals+"]");
  1251.                             if(importXSITYPE.equalsIgnoreCase(testEquals)){
  1252.                                 //System.out.println("CANCELLO");
  1253.                                 prefix = prefixTest.toString().substring(0, prefixTest.length()-1);
  1254.                                 //System.out.println("CANCELLO P["+prefix+"]");
  1255.                                 // Cancello la stringa trovata
  1256.                                 i = i + test.toString().length() +1;
  1257.                                 continue;
  1258.                             }
  1259.                         }
  1260.                     }
  1261.                    
  1262.                     cleanXML.write(xml[i]);
  1263.                     i++;

  1264.                 }else{
  1265.                     cleanXML.write(xml[i]);
  1266.                     i++;
  1267.                 }

  1268.             }
  1269.             byte [] risultato = cleanXML.toByteArray();
  1270.             cleanXML = new ByteArrayOutputStream();
  1271.             //System.out.println("DOPO step 1 ["+new String(risultato)+"] ");
  1272.             cleanXML.close();
  1273.            
  1274.             // Elimino xsi type
  1275.             for(int i=0; i<risultato.length ; ){

  1276.                 if(risultato[i] == ' '){

  1277.                     // Cerco Stringa  " xsi:type=\"xsd:TYPE\""
  1278.                     String XSITYPE_PREFIX = prefix+":type=\"";
  1279.                     if(i+XSITYPE_PREFIX.length()+2 < risultato.length){
  1280.                         StringBuilder test = new StringBuilder("");
  1281.                         int contatoreFineAttributo = 0;
  1282.                         for(int k=1 ; ; k++){
  1283.                             if((i+k)>=risultato.length)
  1284.                                 break;
  1285.                             if((char)risultato[i+k] == '"')
  1286.                                 contatoreFineAttributo++;
  1287.                             test.append((char)risultato[i+k]);
  1288.                             if(contatoreFineAttributo>=2)
  1289.                                 break;
  1290.                         }
  1291.                         //stem.out.println("TROVATO ["+test.toString()+"] START WITH["+XSITYPE_PREFIX+"]");
  1292.                         if(test.toString().startsWith(XSITYPE_PREFIX)){
  1293.                             // Cancello la stringa trovata
  1294.                             //System.out.println("CANCELLO");
  1295.                             i = i + test.toString().length()+1;
  1296.                             continue;
  1297.                         }
  1298.                     }
  1299.                    
  1300.                     cleanXML.write(risultato[i]);
  1301.                     i++;

  1302.                 }else{
  1303.                     cleanXML.write(risultato[i]);
  1304.                     i++;
  1305.                 }

  1306.             }
  1307.             risultato = cleanXML.toByteArray();
  1308.             cleanXML.close();
  1309.            
  1310.             return risultato;

  1311.         } catch(Exception e) {
  1312.             this.logger.error("Utilities.eraserType",e);
  1313.             try{
  1314.                 if(cleanXML!=null)
  1315.                     cleanXML.close();
  1316.             }catch(Exception eis){
  1317.                 // ignore
  1318.             }
  1319.             throw new UtilsException("Eliminazione xsi:type per validazione non riuscita "+e.getMessage(),e);
  1320.         }
  1321.     }  
  1322.    
  1323.    
  1324.    
  1325.    
  1326.    
  1327.    

  1328. }

  1329. class RootElementBody{
  1330.    
  1331.     private String localName;
  1332.     private String namespace;
  1333.     private String xsiType;
  1334.    
  1335.     // Questo elemento viene valorizzato solo nei casi di wsdl encoded dove gli elementi vengono definiti con wsdl:part element e non type.
  1336.     private String namespaceElementoCheContieneXSIType;
  1337.        
  1338.     public RootElementBody(SOAPEnvelope soapEnvelope,Node nodoPadre,boolean rpc, Node n) throws Exception{
  1339.        
  1340.         NamedNodeMap attributes = n.getAttributes();
  1341.         this.localName = n.getLocalName();
  1342.        
  1343.         // Prima verifico presenza di xsi:types ...
  1344.         if(attributes!=null && attributes.getLength()>0){
  1345.             for (int i = 0; i < attributes.getLength(); i++) {
  1346.                 Node attribute = attributes.item(i);
  1347.                 if(attribute instanceof Attr){
  1348.                     Attr a = (Attr) attribute;
  1349.                     //String attrName = a.getName(); // type
  1350.                     //String attrPrefix = a.getPrefix(); // xsi
  1351.                     String attrLocalName = a.getLocalName();
  1352.                     String attrNamespace = a.getNamespaceURI(); // http://www.w3.org/2001/XMLSchema-instance
  1353.                     String value = a.getNodeValue(); // messaggioSII:esitoProcessMessaggioSIIType
  1354.                     //System.out.println("ATTRNAME["+attrName+"] ATTRPREFIX["+attrPrefix+"] ATTRNAMESPACE["+attrNamespace+"] VALUE["+value+"]");
  1355.                     if(WSDLValidator.XMLSCHEMA_INSTANCE_NAMESPACE.equals(attrNamespace) &&
  1356.                             WSDLValidator.XMLSCHEMA_INSTANCE_LOCAL_NAME_TYPE.equals(attrLocalName) &&
  1357.                             value!=null){
  1358.                         String prefix = "";
  1359.                         String typeName = value;
  1360.                         if(value.contains(":")){
  1361.                             prefix = value.split(":")[0];
  1362.                             typeName = value.split(":")[1];
  1363.                         }
  1364.                         this.xsiType = typeName;
  1365.                        
  1366.                         // Cerco namespace corrispondente al prefix.
  1367.                         // 1. cerco prima nel nodo stesso
  1368.                         this.namespace = this.mappingPrefixToNamespace(n, prefix);
  1369.                         if(this.namespace==null){
  1370.                             if(rpc){
  1371.                                 // 2. cerco nel rpc element
  1372.                                 this.namespace = this.mappingPrefixToNamespace(nodoPadre, prefix);
  1373.                                 if(this.namespace==null){
  1374.                                     // 3. cerco nel soap body
  1375.                                     this.namespace = this.mappingPrefixToNamespace(soapEnvelope.getBody(), prefix);
  1376.                                     if(this.namespace==null){
  1377.                                         // 4. cerco nel soap envelope
  1378.                                         this.namespace = this.mappingPrefixToNamespace(soapEnvelope, prefix);
  1379.                                         if(this.namespace==null){
  1380.                                             throw new Exception("[RPCStyle] Namespace (for prefix "+prefix+") not found for element ["+n.getLocalName()+"] with xsi:type=\""+value+"\"");
  1381.                                         }
  1382.                                     }  
  1383.                                 }
  1384.                             }else{
  1385.                                 // 2. cerco nel soap body (il nodo padre)
  1386.                                 this.namespace = this.mappingPrefixToNamespace(nodoPadre, prefix);
  1387.                                 if(this.namespace==null){
  1388.                                     // 3. cerco nel soap envelope
  1389.                                     this.namespace = this.mappingPrefixToNamespace(soapEnvelope, prefix);
  1390.                                     if(this.namespace==null){
  1391.                                         throw new Exception("[DocumentStyle] Namespace (for prefix "+prefix+") not found for element ["+n.getLocalName()+"] with xsi:type=\""+value+"\"");
  1392.                                     }
  1393.                                 }  
  1394.                             }
  1395.                         }
  1396.                     }
  1397.                 }
  1398.             }
  1399.         }
  1400.        
  1401.         if(this.xsiType==null){
  1402.             this.namespace = n.getNamespaceURI();
  1403.         }
  1404.         else{
  1405.             this.namespaceElementoCheContieneXSIType = n.getNamespaceURI();
  1406.         }
  1407.     }
  1408.    
  1409.     private String mappingPrefixToNamespace(Node n,String prefix) {
  1410.         NamedNodeMap attributes = n.getAttributes();
  1411.         if(attributes==null || attributes.getLength()<=0){
  1412.             return null;
  1413.         }
  1414.         for (int i = 0; i < attributes.getLength(); i++) {
  1415.             Node attribute = attributes.item(i);
  1416.             if(attribute instanceof Attr){
  1417.                 Attr a = (Attr) attribute;
  1418.                 String attrName = a.getName(); // type
  1419.                 //String attrPrefix = a.getPrefix(); // xsi
  1420.                 //String attrNamespace = a.getNamespaceURI(); // http://www.w3.org/2001/XMLSchema-instance
  1421.                 String value = a.getNodeValue(); // messaggioSII:esitoProcessMessaggioSIIType
  1422.                 //System.out.println("CHECK XMLNS Search["+prefix+"] ATTRNAME["+attrName+"] ATTRPREFIX["+attrPrefix+"] ATTRNAMESPACE["+attrNamespace+"] VALUE["+value+"]");
  1423.                
  1424.                 if(attrName.startsWith("xmlns")){
  1425.                
  1426.                     if(prefix==null || prefix.equals("")){
  1427.                         if("xmlns".equals(attrName)){
  1428.                             //System.out.println("FOUND! ["+value+"]");
  1429.                             return value;
  1430.                         }
  1431.                     }
  1432.                     else{
  1433.                         if(attrName.equals("xmlns:"+prefix)){
  1434.                             //System.out.println("FOUND! ["+value+"]");
  1435.                             return value;
  1436.                         }
  1437.                     }
  1438.                    
  1439.                 }
  1440.                
  1441.             }
  1442.         }
  1443.         return null;
  1444.     }
  1445.    
  1446.     public String getLocalName() {
  1447.         return this.localName;
  1448.     }
  1449.     public void setLocalName(String localName) {
  1450.         this.localName = localName;
  1451.     }
  1452.     public String getNamespace() {
  1453.         return this.namespace;
  1454.     }
  1455.     public void setNamespace(String namespace) {
  1456.         this.namespace = namespace;
  1457.     }
  1458.     public String getXsiType() {
  1459.         return this.xsiType;
  1460.     }
  1461.     public void setXsiType(String xsiType) {
  1462.         this.xsiType = xsiType;
  1463.     }
  1464.     public String getNamespaceElementoCheContieneXSIType() {
  1465.         return this.namespaceElementoCheContieneXSIType;
  1466.     }
  1467.     public void setNamespaceElementoCheContieneXSIType(
  1468.             String namespaceElementoCheContieneXSIType) {
  1469.         this.namespaceElementoCheContieneXSIType = namespaceElementoCheContieneXSIType;
  1470.     }
  1471.    
  1472.     @Override
  1473.     public String toString(){
  1474.         return RootElementBody.toString(this.localName, this.namespace, this.xsiType, this.namespaceElementoCheContieneXSIType);
  1475.     }
  1476.    
  1477.     public static String toString(String localName,String namespace,String xsiType){
  1478.         return toString(localName, namespace, xsiType, null);
  1479.     }
  1480.     private static String toString(String localName,String namespace,String xsiType,String namespaceElementoCheContieneXSIType){
  1481.         StringBuilder bf = new StringBuilder();
  1482.         if(xsiType==null){
  1483.             bf.append("{");
  1484.             bf.append(namespace);
  1485.             bf.append("}");
  1486.             bf.append(localName);
  1487.         }else{
  1488.             bf.append("[xsi:type=\"{");
  1489.             bf.append(namespace);
  1490.             bf.append("\"}"+xsiType+"]");
  1491.             // Questo elemento viene valorizzato solo nei casi di wsdl encoded dove gli elementi vengono definiti con wsdl:part element e non type.
  1492.             if(namespaceElementoCheContieneXSIType!=null){
  1493.                 bf.append("{");
  1494.                 bf.append(namespaceElementoCheContieneXSIType);
  1495.                 bf.append("}");
  1496.             }
  1497.             bf.append(localName);
  1498.         }
  1499.         return bf.toString();
  1500.     }
  1501. }