AbstractXPathExpressionEngine.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.utils.xml;

  21. import java.io.Reader;
  22. import java.io.StringReader;
  23. import java.util.ArrayList;
  24. import java.util.Enumeration;
  25. import java.util.List;

  26. import javax.xml.soap.SOAPElement;

  27. import org.openspcoop2.utils.LoggerWrapperFactory;
  28. import org.openspcoop2.utils.SemaphoreLock;
  29. import org.openspcoop2.utils.Utilities;
  30. import org.openspcoop2.utils.UtilsException;
  31. import org.openspcoop2.utils.UtilsMultiException;
  32. import org.slf4j.Logger;
  33. import org.w3c.dom.Attr;
  34. import org.w3c.dom.CharacterData;
  35. import org.w3c.dom.Comment;
  36. import org.w3c.dom.Document;
  37. import org.w3c.dom.Element;
  38. import org.w3c.dom.EntityReference;
  39. import org.w3c.dom.NamedNodeMap;
  40. import org.w3c.dom.Node;
  41. import org.w3c.dom.NodeList;

  42. /**
  43.  * Classe utilizzabile per ricerche effettuate tramite espressioni XPath
  44.  *
  45.  * @author Andrea Poli (apoli@link.it)
  46.  * @author $Author$
  47.  * @version $Rev$, $Date$
  48.  */

  49. public abstract class AbstractXPathExpressionEngine {

  50.    
  51.    
  52.     private static Logger logger = LoggerWrapperFactory.getLogger(AbstractXPathExpressionEngine.class);
  53.     public static void setLogger(Logger logger) {
  54.         AbstractXPathExpressionEngine.logger = logger;
  55.     }
  56.    
  57.    
  58.     /*
  59.    
  60.     Per la sintassi vedi: http://www.w3.org/TR/xpath

  61.     Esempio1: /rubrica/persone/nome/text()
  62.     restituisce il valore del tag nome partendo dalla radice del xml (path assoluto)

  63.     Esempio2:
  64.     //nome/text()
  65.     restituisce il valore del tag nome (path relativo)

  66.     Esempio3
  67.     /rubrica/persone/* /text()
  68.     restituisce il valore di tutti i nodi figli del tag persone

  69.     Esempio4
  70.     //citta/@targa
  71.     restituisce per ogni tag citta il valore dell'attributo targa

  72.     Esempio5
  73.     //persona[position()=3]/text()
  74.     restituisce il terzo nodo persona

  75.     Esempio6
  76.     //citta[@targa='mi']/text()
  77.     restituisce il valore della citta che ha come valore dell'attributo targa, mi
  78.    
  79.     Esempio7
  80.     http://saxon.sourceforge.net/saxon6.5.3/expressions.html
  81.     Ci sono le funzioni per content based
  82.       substring-after(name(//soap:Body/*),":")
  83.     Prende il nome dell'elemento dopo il Body. Sbustring per non prendere il namespace
  84.     Devono essere usati per il nome di un elemento.
  85.    
  86.     Altri esempi per avere il nome del primo child.
  87.     Il piu' corretto e' il seguente, il quale non richiede di conoscere ne namespace del soap envelope, ne namespace del primo child, e funziona sia che il child possiede che non possieda un prefix:*/
  88.     // Viene preso il local name del primo elemento figlio dell'ultimo figlio dell'envelope. L'ultimo figlio dell'envelope e' chiaramente il Body (per evitare casi in cui nel messaggio vi sia l'header)
  89.     //ESPRESSIONE:  local-name(/*/*[last()]/*)
  90.    
  91.     // Anche la seguente funziona per trovare il child pero' funziona SOLO se il child possiede un prefix.
  92.     // substring-after(name(/*/*[last()]/*),&#34;:&#34;)
  93.    
  94.     /*
  95.     Esempio8
  96.     Per concatenare piu' risultati
  97.     concat(//citta[@targa='mi']/text(),//citta[@targa='bo']/text())
  98.     */
  99.    
  100.     // Altri esempi:
  101.     // http://msdn.microsoft.com/en-us/library/ms256086.aspx
  102.    
  103.    
  104.     /* ---------- METODI RITORNANO STRINGHE -------------- */
  105.    
  106.     /**
  107.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  108.      *
  109.      * @param element Elemento SOAP da cui estrarre l'oggetto
  110.      * @param dnc DynamicNamespaceContext
  111.      * @param pattern Pattern che identifica l'oggetto
  112.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  113.      * @throws XPathException
  114.      * @throws XPathNotFoundException
  115.      */
  116.     public String getStringMatchPattern(SOAPElement element, DynamicNamespaceContext dnc,String pattern)
  117.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  118.         return (String) this.getMatchPattern(element, dnc, pattern, XPathReturnType.STRING);
  119.     }
  120.    
  121.     /**
  122.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  123.      *
  124.      * @param document Document da cui estrarre l'oggetto
  125.      * @param dnc DynamicNamespaceContext
  126.      * @param pattern Pattern che identifica l'oggetto
  127.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  128.      * @throws XPathException
  129.      * @throws XPathNotFoundException
  130.      */
  131.     public String getStringMatchPattern(Document document, DynamicNamespaceContext dnc,String pattern)
  132.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  133.         return (String) this.getMatchPattern(document.getDocumentElement(), dnc, pattern, XPathReturnType.STRING);
  134.     }
  135.    
  136.     /**
  137.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  138.      *
  139.      * @param element Elemento da cui estrarre l'oggetto
  140.      * @param dnc DynamicNamespaceContext
  141.      * @param pattern Pattern che identifica l'oggetto
  142.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  143.      * @throws XPathException
  144.      * @throws XPathNotFoundException
  145.      */
  146.     public String getStringMatchPattern(Element element, DynamicNamespaceContext dnc,String pattern)
  147.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  148.         return (String) this.getMatchPattern(element, dnc, pattern, XPathReturnType.STRING);
  149.     }
  150.    
  151.     /**
  152.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  153.      *
  154.      * @param contenuto Contenuto da cui estrarre l'oggetto
  155.      * @param dnc DynamicNamespaceContext
  156.      * @param pattern Pattern che identifica l'oggetto
  157.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  158.      * @throws XPathException
  159.      * @throws XPathNotFoundException
  160.      */
  161.     public String getStringMatchPattern(String contenuto, DynamicNamespaceContext dnc,String pattern)
  162.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  163.         return (String) this.getMatchPattern(contenuto, dnc, pattern, XPathReturnType.STRING);
  164.     }
  165.    
  166.    
  167.    
  168.     /* ---------- METODI GENERICI -------------- */
  169.    
  170.     public abstract String getAsString(SOAPElement element);
  171.     public abstract AbstractXMLUtils getXMLUtils();
  172.    
  173.     /**
  174.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  175.      *
  176.      * @param element Elemento SOAP da cui estrarre l'oggetto
  177.      * @param dnc DynamicNamespaceContext
  178.      * @param pattern Pattern che identifica l'oggetto
  179.      * @param returnType Tipo dell'oggetto ritornato
  180.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  181.      * @throws XPathException
  182.      * @throws XPathNotFoundException
  183.      */
  184.     public Object getMatchPattern(SOAPElement element, DynamicNamespaceContext dnc,String pattern, XPathReturnType returnType)
  185.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  186.        
  187.         if(element==null)
  188.             throw new XPathException("element xml undefined");
  189.        
  190.         return this._engine_getMatchPattern(element, null, dnc, pattern, returnType);
  191.     }
  192.    
  193.     /**
  194.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  195.      *
  196.      * @param document Document da cui estrarre l'oggetto
  197.      * @param dnc DynamicNamespaceContext
  198.      * @param pattern Pattern che identifica l'oggetto
  199.      * @param returnType Tipo dell'oggetto ritornato
  200.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  201.      * @throws XPathException
  202.      * @throws XPathNotFoundException
  203.      */
  204.     public Object getMatchPattern(Document document, DynamicNamespaceContext dnc,String pattern, XPathReturnType returnType)
  205.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  206.        
  207.         if(document==null)
  208.             throw new XPathException("document xml undefined");
  209.         if(document.getDocumentElement()==null)
  210.             throw new XPathException("document.element xml undefined");
  211.        
  212.         return this._engine_getMatchPattern(document.getDocumentElement(), null, dnc, pattern, returnType);
  213.        
  214.     }
  215.    
  216.     /**
  217.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  218.      *
  219.      * @param element Elemento da cui estrarre l'oggetto
  220.      * @param dnc DynamicNamespaceContext
  221.      * @param pattern Pattern che identifica l'oggetto
  222.      * @param returnType Tipo dell'oggetto ritornato
  223.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  224.      * @throws XPathException
  225.      * @throws XPathNotFoundException
  226.      */
  227.     public Object getMatchPattern(Element element, DynamicNamespaceContext dnc,String pattern, XPathReturnType returnType)
  228.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  229.        
  230.         if(element==null)
  231.             throw new XPathException("element xml undefined");
  232.        
  233.         return this._engine_getMatchPattern(element, null, dnc, pattern, returnType);
  234.     }
  235.    
  236.     /**
  237.      * Estrae dal contenuto passato come parametro, l'oggetto identificato dal parametro pattern e dal tipo returnType
  238.      *
  239.      * @param content Contenuto da cui estrarre l'oggetto
  240.      * @param dnc DynamicNamespaceContext
  241.      * @param pattern Pattern che identifica l'oggetto
  242.      * @param returnType Tipo dell'oggetto ritornato
  243.      * @return Oggetto identificato dal parametro pattern e dal tipo returnType
  244.      * @throws XPathException
  245.      * @throws XPathNotFoundException
  246.      */
  247.     public Object getMatchPattern(String content, DynamicNamespaceContext dnc,String pattern, XPathReturnType returnType)
  248.         throws XPathException,XPathNotFoundException,XPathNotValidException{
  249.        
  250.         if(content==null)
  251.             throw new XPathException("content undefined");
  252.        
  253.         return this._engine_getMatchPattern(null, content, dnc, pattern, returnType);
  254.        
  255.     }
  256.    
  257.    
  258.    
  259.     /* ---------- ENGINE -------------- */
  260.    
  261.     public abstract Element readXPathElement(Element contenutoAsElement);
  262.    
  263.     //private static Integer synchronizedObjectForBugFWK005ParseXerces = Integer.valueOf(1); // vedi test TestBugFWK005ParseXerces
  264.     private static final org.openspcoop2.utils.Semaphore lockObjectForBugFWK005ParseXerces = new org.openspcoop2.utils.Semaphore("BugFWK005ParseXerces");
  265.     private Object _engine_getMatchPattern(
  266.             Element contenutoAsElement, String contenutoAsString,
  267.             DynamicNamespaceContext dncPrivate,String pattern, XPathReturnType returnType)
  268.             throws XPathException,XPathNotFoundException,XPathNotValidException{

  269.         if( (pattern == null) || (pattern.length() == 0))
  270.             throw new XPathNotFoundException("Pattern di ricerca non fornito");
  271.         if(contenutoAsElement == null && contenutoAsString==null)
  272.             throw new XPathNotFoundException("Contenuto su cui effettuare la ricerca non fornito");
  273.         if(contenutoAsElement != null && contenutoAsString!=null)
  274.             throw new XPathNotFoundException("Contenuto su cui effettuare la ricerca ambiguo");

  275.        
  276.         // Validazione espressione XPAth fornita
  277.         pattern = pattern.trim();
  278.         this.validate(pattern);
  279.        
  280.        
  281.         try{
  282.            
  283.             // 1. Instantiate an XPathFactory.
  284.             javax.xml.xpath.XPathFactory factory = this.getXMLUtils().getXPathFactory();
  285.    
  286.             // 2. Use the XPathFactory to create a new XPath object
  287.             javax.xml.xpath.XPath xpath = factory.newXPath();
  288.             if(xpath==null){
  289.                 throw new Exception("Costruzione xpath non riuscita");
  290.             }
  291.            
  292.             // 3. Set the Namespaces
  293.            
  294.             // 3.1. Clone dnc, verra' modificato in convertNamespaces
  295.             DynamicNamespaceContext dnc = null;
  296.             if(dncPrivate!=null){
  297.                 dnc = (DynamicNamespaceContext) dncPrivate.clone();
  298.             }
  299.            
  300.             // 3.2 // Risoluzione namespace {http:///}
  301.             // NOTA: da utilizzare con {http://namespace}localName
  302.             // BugFix: se per errore viene utilizzato {http://namespace}:localName prima di effettuare la risoluzione del namespace viene eliminato il ':'
  303.             if(dnc!=null){
  304.                 pattern = pattern.replaceAll("}:", "}");
  305.                 pattern = this.convertNamespaces(pattern, dnc);
  306.             }
  307.             //System.out.println("PATTERN: ["+pattern+"]");

  308.             // 3.3 set dnc in xpath
  309.             if(dnc!=null)
  310.                 xpath.setNamespaceContext(dnc);
  311.            
  312.             // 3.4
  313.             // Bug fix: se il contenuto possiede una namespace associato al prefix di default, poi l'xpath engine non trova l'elemento.
  314.             // es. <prova xmlns="www.namespace">TEST</prova> con xpath /prova/text() non funziona.
  315. //          if(dnc.getNamespaceURI(javax.xml.XMLConstants.DEFAULT_NS_PREFIX).equals(javax.xml.XMLConstants.NULL_NS_URI) == false ){
  316. //              //System.out.println("PATCH CONTENUTO PER NAMESPACE DEFAULT: "+dnc.getNamespaceURI(javax.xml.XMLConstants.DEFAULT_NS_PREFIX));
  317. //              contenuto = contenuto.replace("xmlns=\""+dnc.getNamespaceURI(javax.xml.XMLConstants.DEFAULT_NS_PREFIX)+"\"", "");
  318. //          }  
  319.             // !!!! NOTA Il fix sopra indicato non era corretto.
  320.             // e' giusto che non lo trova se viene fornito un xpath senza prefisso, poiche' si sta cercando un elemento che non appartiene a nessun namespace.
  321.             // L'xpath sopra funzionera' su un xml definito come <prova>TEST</prova>
  322.             //
  323.             // Ulteriore spiegazione:
  324.             // But since the nodes you are trying to get use a default namespace, without a prefix, using plain XPath,
  325.             // you can only access them by the local-name() and namespace-uri() attributes. Examples:
  326.             // *[local-name()="HelloWorldResult"]/text()
  327.             // Or:
  328.             // *[local-name()="HelloWorldResult" and namespace-uri()='http://tempuri.org/']/text()
  329.             // Or:
  330.             //*[local-name()="HelloWorldResponse" and namespace-uri()='http://tempuri.org/']/*[
  331.             //
  332.             // Siccome la modalita' di utilizzare il local-name e il namespace-uri in un xpath e' elaborioso, abbiamo aggiunto in openspcoop2
  333.             // la possibilita' di indicare il namespace {namespace} che verra' convertito in un prefix interno utile al funzionamento dell'xpath.
  334.             // Il pattern da fornire  che funziona sull'xml indicato sopra e' /{www.namespace}prova/text()
  335.             // Per ulteriori dettagli vedi metodo convertNamespaces utilizzato in 3.2, all'interno del metodo viene fornita una descrizione dettagliata.
  336.            
  337.                
  338.             // Concatenazione openspcoop.
  339.             if(pattern.startsWith("concat_openspcoop") && pattern.endsWith(")")){
  340.                
  341.                 // Check compatibilita' concat_openspcoop
  342.                 if(returnType.equals(XPathReturnType.STRING)==false){
  343.                     throw new XPathException("Funzione concat_openspcoop non compatibile con un tipo di ritorno: "+returnType.toString());
  344.                 }
  345.                
  346.                 // Fix , la funzione concat non ritorna eccezione se non riesce a risolvere qualche espressione, e contiene cmq delle costanti.
  347.                 // La concatenazione openspcoop, invece ritornera' errore.
  348.                 String param = pattern.substring("concat_openspcoop(".length(),pattern.length()-1);
  349.                 String [] params =param.split(",");
  350.                 StringBuilder bfResult = new StringBuilder();
  351.                 for(int i=0; i<params.length;i++){
  352.                    
  353.                     // Check se abbiamo una costante od una espressione da valutare
  354.                     if(params[i].startsWith("\"") && params[i].endsWith("\"")){
  355.                    
  356.                         // COSTANTE
  357.                         bfResult.append(params[i].substring(1,(params[i].length()-1)));
  358.                    
  359.                     }else{
  360.                        
  361.                         // 4. Reader
  362.                         Reader reader = null;
  363.                         if(contenutoAsString!=null){
  364.                             try{
  365.                                 reader = new StringReader(contenutoAsString);
  366.                             }catch(Exception e){
  367.                                 try{
  368.                                     if( reader != null )
  369.                                         reader.close();
  370.                                 } catch(Exception er) {
  371.                                     // close
  372.                                 }
  373.                                 throw e;
  374.                             }      
  375.                         }
  376.                        
  377.                         // ESPRESSIONE
  378.                         // 5. Compile an XPath string into an XPathExpression
  379.                         javax.xml.xpath.XPathExpression expression = null;
  380.                         try{
  381.                             expression = xpath.compile(params[i]);
  382.                         }catch(Exception e){
  383.                             if(Utilities.existsInnerMessageException(e, "Prefix must resolve to a namespace", true)){
  384.                                 // e' stato usato un prefisso nell'espressione XPath che non e' risolvibile accedendo ai namespaces del messaggio (dnc)
  385.                                 throw new XPathNotFoundException("Espressione XPATH contenuta in concat_openspcoop ("+params[i]+") non applicabile al messaggio: "+Utilities.getInnerMessageException(e, "Prefix must resolve to a namespace", true));
  386.                             }
  387.                             else if(Utilities.existsInnerException(e,javax.xml.transform.TransformerException.class)){
  388.                                 throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+Utilities.getInnerException(e, javax.xml.transform.TransformerException.class).getMessage()+")",e);
  389.                             }else{
  390.                                 if(e.getCause()!=null){
  391.                                     throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  392.                                 }else{
  393.                                     throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+e.getMessage()+")",e);
  394.                                 }
  395.                             }  
  396.                         }
  397.                         if(expression==null){
  398.                             throw new Exception("Costruzione XPathExpression non riuscita per espressione contenuta in concat_openspcoop ("+params[i]+")");
  399.                         }
  400.                
  401.                                                
  402.                         // 6. Evaluate the XPath expression on an input document
  403.                         String result = null;
  404.                         try{
  405.                             if(reader!=null) {
  406.                                 //synchronized (AbstractXPathExpressionEngine.synchronizedObjectForBugFWK005ParseXerces) { // vedi test TestBugFWK005ParseXerces
  407.                                 SemaphoreLock lock = lockObjectForBugFWK005ParseXerces.acquire("concat_openspcoopEvaluate");
  408.                                 try {
  409.                                     result = expression.evaluate(new org.xml.sax.InputSource(reader));
  410.                                 }finally {
  411.                                     lockObjectForBugFWK005ParseXerces.release(lock, "concat_openspcoopEvaluate");
  412.                                 }
  413.                             }
  414.                             else {
  415.                                 result = expression.evaluate(this.readXPathElement(contenutoAsElement));
  416.                             }
  417.                         }catch(Exception e){
  418.                             if(Utilities.existsInnerException(e,"com.sun.org.apache.xpath.internal.XPathException")){
  419.                                 throw new Exception("Valutazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+Utilities.getInnerException(e, "com.sun.org.apache.xpath.internal.XPathException").getMessage()+")",e);
  420.                             }
  421.                             else if(Utilities.existsInnerException(e,org.apache.xpath.XPathException.class)){
  422.                                 throw new Exception("Valutazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+Utilities.getInnerException(e, org.apache.xpath.XPathException.class).getMessage()+")",e);
  423.                             }
  424.                             else{
  425.                                 if(e.getCause()!=null){
  426.                                     throw new Exception("Valutazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  427.                                 }else{
  428.                                     throw new Exception("Valutazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+e.getMessage()+")",e);
  429.                                 }
  430.                             }
  431.                         }
  432.                         if(reader!=null)
  433.                             reader.close();
  434.                
  435.                         if(result == null || "".equals(result)){
  436.                             // DEVE ESSERE LANCIATA ECCEZIONE, E' PROPRIO LA FUNZIONALITA DI OPENSPCOOP!
  437.                             // Il Concat normale non lancia eccezione e ritorna stringa vuota.
  438.                             // Verificato con cxf soap engine
  439.                             AbstractXPathExpressionEngine.logger.debug("nessun match trovato per l'espressione xpath contenuta in concat_openspcoop ("+params[i]+")");
  440.                             throw new XPathNotFoundException("nessun match trovato per l'espressione xpath contenuta in concat_openspcoop ("+params[i]+")");
  441.                         }
  442.                         else{
  443.                             bfResult.append(result);
  444.                         }
  445.                     }
  446.                 }
  447.                
  448.                 if(bfResult.length()<=0){
  449.                     StringBuilder bfDNC = new StringBuilder();
  450.                     Enumeration<?> en = dnc.getPrefixes();
  451.                     while (en.hasMoreElements()) {
  452.                         String prefix = (String) en.nextElement();
  453.                         bfDNC.append("\n\t- ");
  454.                         bfDNC.append("[").append(prefix).append("]=[").append(dnc.getNamespaceURI(prefix)).append("]");
  455.                     }
  456.                     throw new XPathNotFoundException("nessun match trovato per l'espressione xpath (concat_openspcoop) ["+pattern+"] DynamicNamespaceContext:"+bfDNC.toString());
  457.                    
  458.                 }else{
  459.                     return bfResult.toString();
  460.                 }

  461.             }else{
  462.                
  463.                 // 4. Reader
  464.                 Reader reader = null;
  465.                 if(contenutoAsString!=null){
  466.                     try{
  467.                         reader = new StringReader(contenutoAsString);
  468.                     }catch(Exception e){
  469.                         try{
  470.                             if( reader != null )
  471.                                 reader.close();
  472.                         } catch(Exception er) {
  473.                             // close
  474.                         }
  475.                         throw e;
  476.                     }      
  477.                 }
  478.                
  479.                
  480.                 // 5. Compile an XPath string into an XPathExpression
  481.                 javax.xml.xpath.XPathExpression expression = null;
  482.                 try{
  483.                     expression = xpath.compile(pattern);
  484.                 }catch(Exception e){
  485.                     if(Utilities.existsInnerMessageException(e, "Prefix must resolve to a namespace", true)){
  486.                         // e' stato usato un prefisso nell'espressione XPath che non e' risolvibile accedendo ai namespaces del messaggio (dnc)
  487.                         throw new XPathNotFoundException("Espressione XPATH non applicabile al messaggio: "+Utilities.getInnerMessageException(e, "Prefix must resolve to a namespace", true));
  488.                     }
  489.                     else if(Utilities.existsInnerException(e,javax.xml.transform.TransformerException.class)){
  490.                         throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+Utilities.getInnerException(e, javax.xml.transform.TransformerException.class).getMessage()+")",e);
  491.                     }else{
  492.                         if(e.getCause()!=null){
  493.                             throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  494.                         }else{
  495.                             throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+e.getMessage()+")",e);
  496.                         }
  497.                     }
  498.                 }
  499.                 if(expression==null){
  500.                     throw new Exception("Costruzione XPathExpression non riuscita");
  501.                 }
  502.        
  503.                 // 6. Evaluate the XPath expression on an input document
  504.                 Object result = null;
  505.                 try{
  506.                     if(reader!=null) {
  507.                         //synchronized (AbstractXPathExpressionEngine.synchronizedObjectForBugFWK005ParseXerces) { // vedi test TestBugFWK005ParseXerces
  508.                         SemaphoreLock lock = lockObjectForBugFWK005ParseXerces.acquire("standardEvaluate");
  509.                         try {
  510.                             result = expression.evaluate(new org.xml.sax.InputSource(reader),returnType.getValore());
  511.                         }finally {
  512.                             lockObjectForBugFWK005ParseXerces.release(lock, "standardEvaluate");
  513.                         }
  514.                     }else{
  515.                         result = expression.evaluate(this.readXPathElement(contenutoAsElement),returnType.getValore());
  516.                     }
  517.                 }catch(Exception e){
  518.                     if(Utilities.existsInnerException(e,"com.sun.org.apache.xpath.internal.XPathException")){
  519.                         throw new Exception("Valutazione dell'espressione XPATH ha causato un errore ("+Utilities.getInnerException(e, "com.sun.org.apache.xpath.internal.XPathException").getMessage()+")",e);
  520.                     }
  521.                     else if(Utilities.existsInnerException(e,org.apache.xpath.XPathException.class)){
  522.                         throw new Exception("Valutazione dell'espressione XPATH ha causato un errore ("+Utilities.getInnerException(e, org.apache.xpath.XPathException.class).getMessage()+")",e);
  523.                     }
  524.                     else{
  525.                         if(e.getCause()!=null){
  526.                             throw new Exception("Valutazione dell'espressione XPATH ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  527.                         }else{
  528.                             throw new Exception("Valutazione dell'espressione XPATH ha causato un errore ("+e.getMessage()+")",e);
  529.                         }
  530.                     }
  531.                 }
  532.                 if(reader!=null)
  533.                     reader.close();
  534.        
  535.                 boolean notFound = false;
  536.                 if(result == null){
  537.                     notFound = true;
  538.                 }
  539.                 else if(result instanceof String){
  540.                     if("".equals(result)){
  541.                         notFound = true;
  542.                     }
  543.                 }
  544.                 else if( (XPathReturnType.NODESET.equals(returnType)) && (result instanceof NodeList)){
  545.                     if(((NodeList)result).getLength()<=0){
  546.                         notFound=true;
  547.                     }
  548.                 }
  549.                
  550.                 if(notFound){
  551.                     //log.info("ContentBased, nessun match trovato");
  552.                     StringBuilder bfDNC = new StringBuilder();
  553.                     Enumeration<?> en = dnc.getPrefixes();
  554.                     while (en.hasMoreElements()) {
  555.                         String prefix = (String) en.nextElement();
  556.                         bfDNC.append("\n\t- ");
  557.                         bfDNC.append("[").append(prefix).append("]=[").append(dnc.getNamespaceURI(prefix)).append("]");
  558.                     }
  559.                     throw new XPathNotFoundException("nessun match trovato per l'espressione xpath ["+pattern+"] DynamicNamespaceContext:"+bfDNC.toString());
  560.                 }
  561.                
  562.                 return result;
  563.            
  564.             }
  565.        
  566.         }catch(XPathNotFoundException ex){
  567.             throw ex;
  568.         }catch(Exception e){
  569.             throw new XPathException("getMatchPattern pattern["+pattern+"] error: "+e.getMessage(),e);
  570.         }
  571.     }
  572.    
  573.    
  574.    
  575.    
  576.    
  577.     /* ---------- VALIDATORE -------------- */
  578.    
  579.     public void validate(String path) throws XPathNotValidException{
  580.         try{
  581.            
  582.             path = path.trim();
  583.                
  584.             // Instantiate an XPathFactory.
  585.             javax.xml.xpath.XPathFactory factory = this.getXMLUtils().getXPathFactory();
  586.    
  587.             // Use the XPathFactory to create a new XPath object
  588.             javax.xml.xpath.XPath xpath = factory.newXPath();
  589.             if(xpath==null){
  590.                 throw new Exception("Costruzione xpath non riuscita");
  591.             }
  592.            
  593.             // 3. Repleace the Namespaces:
  594.             path = path.replaceAll("}:", "}");
  595.             int index = 0;
  596.             while (path.indexOf("{")!=-1){
  597.                 int indexStart = path.indexOf("{");
  598.                 int indexEnd = path.indexOf("}");
  599.                 if(indexEnd==-1){
  600.                     throw new Exception("{ utilizzato senza la rispettiva chiusura }");
  601.                 }
  602.                 String namespace = path.substring(indexStart+"{".length(),indexEnd);
  603.                 if(namespace==null || namespace.equals("")){
  604.                     throw new Exception("Namespace non indicato tra {}");
  605.                 }
  606.                 String prefix = "a"+index+":";
  607.                 index++;
  608.                 path = path.replace("{"+namespace+"}", prefix);
  609.             }
  610.             //System.out.println("PATTERN PER VALIDAZIONE: ["+path+"]");
  611.            
  612.             if(path.startsWith("concat_openspcoop")){
  613.                 // funzione concat
  614.                 String param = path.substring("concat_openspcoop(".length(),path.length()-1);
  615.                 String [] params =param.split(",");
  616.                 for(int i=0; i<params.length;i++){
  617.                    
  618.                     // Check se abbiamo una costante od una espressione da valutare
  619.                     if(params[i].startsWith("\"") && params[i].endsWith("\"")){
  620.                    
  621.                         // COSTANTE
  622.                    
  623.                     }else{
  624.                        
  625.                         javax.xml.xpath.XPathExpression expression = null;
  626.                         try{
  627.                             expression = xpath.compile(params[i]);
  628.                         }catch(Exception e){
  629.                             if(Utilities.existsInnerException(e,javax.xml.transform.TransformerException.class)){
  630.                                 throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+Utilities.getInnerException(e, javax.xml.transform.TransformerException.class).getMessage()+")",e);
  631.                             }else{
  632.                                 if(e.getCause()!=null){
  633.                                     throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  634.                                 }else{
  635.                                     throw new Exception("Compilazione dell'espressione XPATH contenuta in concat_openspcoop ("+params[i]+") ha causato un errore ("+e.getMessage()+")",e);
  636.                                 }
  637.                             }          
  638.                         }
  639.                         if(expression==null){
  640.                             throw new Exception("Costruzione XPathExpression non riuscita per espressione contenuta in concat_openspcoop ("+params[i]+")");
  641.                         }
  642.                        
  643.                     }
  644.                 }
  645.             }
  646.             else{
  647.                 // Compile an XPath string into an XPathExpression
  648.                 javax.xml.xpath.XPathExpression expression = null;
  649.                 try{
  650.                     expression = xpath.compile(path);
  651.                 }catch(Exception e){
  652.                     if(Utilities.existsInnerException(e,javax.xml.transform.TransformerException.class)){
  653.                         throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+Utilities.getInnerException(e, javax.xml.transform.TransformerException.class).getMessage()+")",e);
  654.                     }else{
  655.                         if(e.getCause()!=null){
  656.                             throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+(Utilities.getLastInnerException(e.getCause())).getMessage()+")",e);
  657.                         }else{
  658.                             throw new Exception("Compilazione dell'espressione XPATH ha causato un errore ("+e.getMessage()+")",e);
  659.                         }
  660.                     }  
  661.                 }
  662.                 if(expression==null){
  663.                     throw new Exception("Costruzione XPathExpression non riuscita");
  664.                 }
  665.             }
  666.         }catch(Exception e){
  667.             throw new XPathNotValidException("Validazione dell'xpath indicato ["+path+"] fallita: "+e.getMessage(),e);
  668.         }
  669.     }
  670.    
  671.    
  672.    
  673.    
  674.    
  675.    
  676.    
  677.    
  678.    
  679.     /* -------------- UTILITIES PUBBLICHE ------------------- */
  680.    
  681.     /**
  682.      * Ritorna la rappresentazione testuale di una lista di nodi
  683.      *
  684.      * @param rootNode
  685.      * @return rappresentazione testuale di una lista di nodi
  686.      */
  687.     public String toString(NodeList rootNode){
  688.        
  689.         StringBuilder resultBuffer = new StringBuilder();
  690.         this.toString(rootNode,resultBuffer,1);
  691.         return resultBuffer.toString();
  692.        
  693.     }
  694.     public List<String> toList(NodeList rootNode){
  695.        
  696.         return this.toList(rootNode,1);
  697.        
  698.     }
  699.    

  700.    
  701.     /* -------------- UTILITIES PRIVATE ------------------- */
  702.     private int _prefixIndex = 0;
  703.     private synchronized int _getNextPrefixIndex(){
  704.         this._prefixIndex++;
  705.         return this._prefixIndex;
  706.     }
  707.     private static final String AUTO_PREFIX = "_op2PrefixAutoGeneratedIndex";
  708.     private String convertNamespaces(String path,DynamicNamespaceContext dnc)throws UtilsException{
  709.         while (path.indexOf("{")!=-1){
  710.             int indexStart = path.indexOf("{");
  711.             int indexEnd = path.indexOf("}");
  712.             if(indexEnd==-1){
  713.                 throw new UtilsException("Errore durante l'interpretazione del valore ["+path+"]: { utilizzato senza la rispettiva chiusura }");
  714.             }
  715.             String namespace = path.substring(indexStart+"{".length(),indexEnd);
  716.             String prefix = dnc.getPrefix(namespace);
  717.             //System.out.println("PREFIX["+prefix+"]->NS["+namespace+"]");
  718.             if(prefix!=null && !javax.xml.XMLConstants.NULL_NS_URI.equals(prefix)){
  719.                 prefix = prefix+":";
  720.             }
  721.             else{
  722.                 // aggiungo un prefisso nuovo anche nel caso di prefix "" per gestire la problematica che si presente in questo caso:
  723.                 // String xmlCampione = "<prova xmlns=\"www.namespace\">TEST</prova>";
  724.                 // NON FUNZIONA con un pattern = "/prova/text()"; (poiche' l'elemento prova ha un namespace, quello di default, mentre nell'xpath non viene indicato)
  725.                 //              Questo pattern sarebbe quello generato anche dopo la conversione dei namespace se il prefisso e' javax.xml.XMLConstants.NULL_NS_URI
  726.                 // FUNZIONA con un pattern = "*[local-name()='prova' and namespace-uri()='www.namespace']/text()"; ma e' piu' elaborato
  727.                 // FUNZIONA se registriamo un nuovo prefix da utilizzare solo nel pattern, ad esempio con un pattern = "/_op2PrefixAutoGeneratedIndexNUMBER:prova/text()"
  728.                 //          dove il prefisso auto-generato _op2PrefixAutoGeneratedIndexNUMBER e' associato al namespace www.namespace nel dnc.
  729.                 prefix = AbstractXPathExpressionEngine.AUTO_PREFIX + this._getNextPrefixIndex();
  730.                 dnc.addNamespace(prefix, namespace);
  731.                 prefix = prefix+":";
  732.                 //System.out.println("CASO SPECIALEEEEEEEEEEEEEEEE");
  733.             }
  734.             path = path.replace("{"+namespace+"}", prefix);
  735.         }
  736.         return path;
  737.     }
  738.    
  739.     private void toString(NodeList rootNode,StringBuilder resultBuffer, int livello){
  740.        
  741. //      for(int index = 0; index < rootNode.getLength();index ++){
  742. //          Node aNode = rootNode.item(index);
  743. //          try {
  744. //              System.out.println("DEBUG (livello:"+livello+"): "+getXMLUtils().toString(aNode));
  745. //          }catch(Exception e) {}
  746. //      }
  747.        
  748.         if (rootNode.getLength()==1 &&
  749.                 (rootNode.item(0).getNodeType()==Node.TEXT_NODE || rootNode.item(0).getNodeType()==Node.ATTRIBUTE_NODE) &&
  750.                 resultBuffer.length()==0){
  751.             //System.out.println("TEXT ["+rootNode.item(0).getNodeType()+"] confronto con ["+Node.TEXT_NODE+"] or ["+Node.ATTRIBUTE_NODE+"]");
  752.             // BugEntityReferences: il metodo getTextContent e anche getNodeValue risolve le entity references
  753.             //String textNodeValue = rootNode.item(0).getTextContent();
  754.             String textNodeValue = null;
  755.             try {
  756.                 textNodeValue = _getTextValue_fixEntityReferencies(rootNode.item(0));
  757.             }catch(Throwable t) {
  758.                 textNodeValue = rootNode.item(0).getTextContent();
  759.             }
  760.             resultBuffer.append(textNodeValue);
  761.             return;
  762.         }
  763.         boolean findElementoRisultatoMultiplo = false;
  764.         for(int index = 0; index < rootNode.getLength();index ++){
  765.             Node aNode = rootNode.item(index);
  766.             //System.out.println("NODE["+index+"] ["+aNode.getNodeType()+"] confronto con  ["+Node.ELEMENT_NODE+"]");
  767.             if (aNode.getNodeType() == Node.ELEMENT_NODE){
  768.                 NodeList childNodes = aNode.getChildNodes();
  769.                
  770.                 if (childNodes.getLength() > 0){
  771.                    
  772.                     boolean hasChildNodes = false;
  773.                     for(int i=0;i<childNodes.getLength();i++){
  774.                         // elimino i text node che possono contenere "\n" con axiom
  775.                         Node n = childNodes.item(i);
  776.                         if(n.hasChildNodes()){
  777.                             hasChildNodes = true;
  778.                             break;
  779.                         }
  780.                     }
  781.                    
  782.                     if (hasChildNodes){
  783.                         resultBuffer.append("<"+aNode.getNodeName());

  784.                         this.printAttributes(aNode,resultBuffer);

  785.                         resultBuffer.append(">");
  786.                        
  787.                         this.toString(aNode.getChildNodes(), resultBuffer, (livello+1));
  788.                         resultBuffer.append("</"+aNode.getNodeName()+">");
  789.                     }
  790.                     else {
  791.                         resultBuffer.append("<"+aNode.getNodeName());
  792.                        
  793.                         this.printAttributes(aNode,resultBuffer);
  794.                                            
  795.                         // BugEntityReferences: il metodo getTextContent e anche getNodeValue risolve le entity references
  796.                         // String textNodeValue = aNode.getTextContent();
  797.                         String textNodeValue = null;
  798.                         try {
  799.                             textNodeValue = _getTextValue_fixEntityReferencies(aNode);
  800.                         }catch(Throwable t) {
  801.                             textNodeValue = aNode.getTextContent();
  802.                         }
  803.                        
  804.                         resultBuffer.append(">")
  805.                             .append(textNodeValue)
  806.                             .append("</").append(aNode.getNodeName()).append(">");
  807.                     }
  808.                 }
  809.             }
  810.             // Risultati multipli per uno stesso elemento
  811.             else if ( (livello==1) && (aNode.getNodeType() == Node.TEXT_NODE || aNode.getNodeType() == Node.ATTRIBUTE_NODE) ){
  812.                 if(findElementoRisultatoMultiplo){
  813.                     resultBuffer.append(", ");
  814.                 }
  815.                 else {
  816.                     findElementoRisultatoMultiplo = true;
  817.                 }
  818.                 // BugEntityReferences: il metodo getTextContent e anche getNodeValue risolve le entity references
  819.                 //String textNodeValue = aNode.getTextContent();
  820.                 String textNodeValue = null;
  821.                 try {
  822.                     textNodeValue = _getTextValue_fixEntityReferencies(aNode);
  823.                 }catch(Throwable t) {
  824.                     textNodeValue = aNode.getTextContent();
  825.                 }
  826.                 resultBuffer.append("["+index+"]="+textNodeValue);
  827.             }
  828.         }
  829.     }
  830.    
  831.     private String _getTextValue_fixEntityReferencies(Node valueEle) throws Exception {
  832.        
  833.         StringBuilder sb = new StringBuilder();
  834.        
  835.         if(valueEle.getNodeType()==Node.TEXT_NODE || valueEle.getNodeType()==Node.ATTRIBUTE_NODE) {
  836.             //sb.append(valueEle.getTextContent());
  837.             // FIX:
  838.             sb.append(getXMLUtils().toString(valueEle,true));
  839.         }
  840.         else {
  841.             NodeList nl = valueEle.getChildNodes();
  842.             for (int i = 0; i < nl.getLength(); i++) {
  843.                 Node item = nl.item(i);
  844.                 if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
  845.                     //sb.append(item.getNodeValue());
  846.                     // FIX:
  847.                     sb.append(getXMLUtils().toString(item,true));
  848.                 }
  849.             }
  850.         }
  851.         return sb.toString();
  852.     }
  853.    
  854.     private List<String> toList(NodeList rootNode,int livello){
  855.        
  856.         List<String> l = new ArrayList<>();
  857.        
  858.         if (rootNode.getLength()==1 && rootNode.item(0).getNodeType()==Node.TEXT_NODE){
  859.             //System.out.println("TEXT ["+rootNode.item(0).getNodeType()+"] confronto con ["+Node.TEXT_NODE+"]");
  860.             l.add(rootNode.item(0).getTextContent());
  861.             return l;
  862.         }
  863.         for(int index = 0; index < rootNode.getLength();index ++){
  864.             Node aNode = rootNode.item(index);
  865.             //System.out.println("NODE["+index+"] ["+aNode.getNodeType()+"] confronto con  ["+Node.ELEMENT_NODE+"]");
  866.             if (aNode.getNodeType() == Node.ELEMENT_NODE){
  867.                 NodeList childNodes = aNode.getChildNodes();
  868.                
  869.                 if (childNodes.getLength() > 0){
  870.                    
  871.                     StringBuilder resultBuffer = new StringBuilder();
  872.                    
  873.                     boolean hasChildNodes = false;
  874.                     for(int i=0;i<childNodes.getLength();i++){
  875.                         // elimino i text node che possono contenere "\n" con axiom
  876.                         Node n = childNodes.item(i);
  877.                         if(n.hasChildNodes()){
  878.                             hasChildNodes = true;
  879.                             break;
  880.                         }
  881.                     }
  882.                    
  883.                     if (hasChildNodes){
  884.                         resultBuffer.append("<"+aNode.getNodeName());

  885.                         this.printAttributes(aNode,resultBuffer);

  886.                         resultBuffer.append(">");
  887.                        
  888.                         this.toString(aNode.getChildNodes(), resultBuffer, (livello+1));
  889.                         resultBuffer.append("</"+aNode.getNodeName()+">");
  890.                     }
  891.                     else {
  892.                         resultBuffer.append("<"+aNode.getNodeName());
  893.                        
  894.                         this.printAttributes(aNode,resultBuffer);
  895.                        
  896.                         resultBuffer.append(">"+aNode.getTextContent()+ "</"+aNode.getNodeName()+">");
  897.                     }
  898.                    
  899.                     l.add(resultBuffer.toString());
  900.                 }
  901.             }
  902.             // Risultati multipli per uno stesso elemento
  903.             else if ( (livello==1) && (aNode.getNodeType() == Node.TEXT_NODE) ){
  904.                 l.add(aNode.getTextContent());
  905.             }
  906.         }
  907.        
  908.         return l;
  909.     }
  910.    
  911.     private void printAttributes(Node aNode,StringBuilder resultBuffer){
  912.         NamedNodeMap attr = aNode.getAttributes();
  913.         for (int i=0;i<attr.getLength();i++){
  914.             Node item = attr.item(i);
  915.             if(item instanceof Attr){
  916.                 Attr attribute = (Attr) item;
  917.                 //System.out.println("PREFIX["+attribute.getPrefix()+"] LOCALNAME=["+attribute.getLocalName()+"] NAMESPACE["+attribute.getNodeValue()+"]");
  918.                 String prefix = attribute.getPrefix();
  919.                 if(prefix!=null && !"".equals(prefix)){
  920.                     prefix = prefix + ":";
  921.                 }else{
  922.                     prefix = "";
  923.                 }
  924.                 // BugEntityReferences: il metodo getTextContent e anche getNodeValue risolve le entity references
  925.                 //String value = attribute.getNodeValue();
  926.                 String value = null;
  927.                 try {
  928.                     value = _getTextValue_fixEntityReferencies(attribute);
  929.                 }catch(Throwable t) {
  930.                     value = attribute.getNodeValue();
  931.                 }
  932.                 resultBuffer.append(" "+prefix+attribute.getLocalName()+"=\""+value+"\"");
  933.             }else{
  934.                 resultBuffer.append(" "+item.toString());
  935.             }
  936.         }
  937.     }
  938.    
  939.    
  940.     public static String extractAndConvertResultAsString(String contentAsString,DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  941.         return AbstractXPathExpressionEngine._extractAndConvertResultAsString(null, contentAsString,
  942.                 dnc, xPathEngine, pattern, log);
  943.     }
  944.     public static String extractAndConvertResultAsString(Element element,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  945.         DynamicNamespaceContext dnc = new DynamicNamespaceContext();
  946.         dnc.findPrefixNamespace(element);
  947.         return AbstractXPathExpressionEngine._extractAndConvertResultAsString(element, null,
  948.                 dnc, xPathEngine, pattern, log);
  949.     }
  950.     public static String extractAndConvertResultAsString(Element element,DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  951.         return AbstractXPathExpressionEngine._extractAndConvertResultAsString(element, null,
  952.                 dnc, xPathEngine, pattern, log);
  953.     }
  954.     private static String _extractAndConvertResultAsString(Element element,String contentAsString,
  955.             DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  956.        
  957.         // Provo a cercarlo prima come Node
  958.         NodeList nodeList = null;
  959.         Exception exceptionNodeSet = null;
  960.         String risultato = null;
  961.         try{
  962.             if(element!=null) {
  963.                 nodeList = (NodeList) xPathEngine.getMatchPattern(element, dnc, pattern,XPathReturnType.NODESET);
  964.             }
  965.             else {
  966.                 nodeList = (NodeList) xPathEngine.getMatchPattern(contentAsString, dnc, pattern,XPathReturnType.NODESET);
  967.             }
  968.             if(nodeList!=null){
  969.                 risultato = xPathEngine.toString(nodeList);
  970.             }
  971.         }catch(Exception e){
  972.             exceptionNodeSet = e;
  973.         }
  974.        
  975.         // Se non l'ho trovato provo a cercarlo come string (es. il metodo sopra serve per avere l'xml, ma fallisce in caso di concat, in caso di errori di concat_openspcoop....)
  976.         // Insomma il caso dell'xml sopra e' quello speciale, che pero' deve essere eseguito prima, perche' altrimenti il caso string sotto funziona sempre, e quindi non si ottiene mai l'xml.
  977.         if(risultato==null || "".equals(risultato)){
  978.             try{
  979.                 if(element!=null) {
  980.                     risultato = xPathEngine.getStringMatchPattern(element, dnc, pattern);
  981.                 }
  982.                 else {
  983.                     risultato = xPathEngine.getStringMatchPattern(contentAsString, dnc, pattern);
  984.                 }
  985.             }catch(Exception e){
  986.                 if(exceptionNodeSet!=null){
  987.                     log.debug("Errore avvenuto durante la getStringMatchPattern("+pattern
  988.                             +") ("+e.getMessage()+") invocata in seguito all'errore dell'invocazione getMatchPattern("+
  989.                             pattern+",NODESET): "+exceptionNodeSet.getMessage(),exceptionNodeSet);
  990.                 }
  991.                 // lancio questo errore e se presente anche quello con la ricerca notset nodoset.
  992.                 if(exceptionNodeSet!=null) {
  993.                     throw new UtilsMultiException(e,exceptionNodeSet);
  994.                 }
  995.                 else {
  996.                     throw e;
  997.                 }
  998.             }
  999.         }
  1000.        
  1001.         if(risultato == null || "".equals(risultato)){
  1002.             if(exceptionNodeSet!=null){
  1003.                 log.debug("Non sono stati trovati risultati tramite l'invocazione del metodo getStringMatchPattern("+pattern
  1004.                         +") invocato in seguito all'errore dell'invocazione getMatchPattern("+
  1005.                         pattern+",NODESET): "+exceptionNodeSet.getMessage(),exceptionNodeSet);
  1006.                 // lancio questo errore.
  1007.                 // Questo errore puo' avvenire perche' ho provato a fare xpath con nodeset
  1008.                 //throw exceptionNodeSet;
  1009.             }
  1010.         }
  1011.        
  1012.         return risultato;
  1013.     }
  1014.    
  1015.    
  1016.    
  1017.     public static List<String> extractAndConvertResultAsList(String contentAsString,DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  1018.         return AbstractXPathExpressionEngine._extractAndConvertResultAsList(null, contentAsString,
  1019.                 dnc, xPathEngine, pattern, log);
  1020.     }
  1021.     public static List<String> extractAndConvertResultAsList(Element element,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  1022.         DynamicNamespaceContext dnc = new DynamicNamespaceContext();
  1023.         dnc.findPrefixNamespace(element);
  1024.         return AbstractXPathExpressionEngine._extractAndConvertResultAsList(element, null,
  1025.                 dnc, xPathEngine, pattern, log);
  1026.     }
  1027.     public static List<String> extractAndConvertResultAsList(Element element,DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  1028.         return AbstractXPathExpressionEngine._extractAndConvertResultAsList(element, null,
  1029.                 dnc, xPathEngine, pattern, log);
  1030.     }
  1031.     private static List<String> _extractAndConvertResultAsList(Element element,String contentAsString,
  1032.             DynamicNamespaceContext dnc,AbstractXPathExpressionEngine xPathEngine, String pattern, Logger log) throws Exception {
  1033.        
  1034.        
  1035.         // Provo a cercarlo prima come Node
  1036.         NodeList nodeList = null;
  1037.         Exception exceptionNodeSet = null;
  1038.         List<String> risultato = new ArrayList<>();
  1039.         try{
  1040.             if(element!=null) {
  1041.                 nodeList = (NodeList) xPathEngine.getMatchPattern(element, dnc, pattern,XPathReturnType.NODESET);
  1042.             }
  1043.             else {
  1044.                 nodeList = (NodeList) xPathEngine.getMatchPattern(contentAsString, dnc, pattern,XPathReturnType.NODESET);
  1045.             }
  1046.             if(nodeList!=null){
  1047.                 risultato = xPathEngine.toList(nodeList);
  1048.             }
  1049.         }catch(Exception e){
  1050.             exceptionNodeSet = e;
  1051.         }
  1052.        
  1053.         // Se non l'ho trovato provo a cercarlo come string (es. il metodo sopra serve per avere l'xml, ma fallisce in caso di concat, in caso di errori di concat_openspcoop....)
  1054.         // Insomma il caso dell'xml sopra e' quello speciale, che pero' deve essere eseguito prima, perche' altrimenti il caso string sotto funziona sempre, e quindi non si ottiene mai l'xml.
  1055.         if(risultato==null || risultato.isEmpty()){
  1056.             try{
  1057.                 String s = null;
  1058.                 if(element!=null) {
  1059.                     s = xPathEngine.getStringMatchPattern(element, dnc, pattern);
  1060.                 }
  1061.                 else {
  1062.                     s = xPathEngine.getStringMatchPattern(contentAsString, dnc, pattern);
  1063.                 }
  1064.                 if(risultato==null) {
  1065.                     risultato = new ArrayList<>();
  1066.                 }
  1067.                 risultato.add(s);
  1068.             }catch(Exception e){
  1069.                 if(exceptionNodeSet!=null){
  1070.                     log.debug("Errore avvenuto durante la getStringMatchPattern("+pattern
  1071.                             +") ("+e.getMessage()+") invocata in seguito all'errore dell'invocazione getMatchPattern("+
  1072.                             pattern+",NODESET): "+exceptionNodeSet.getMessage(),exceptionNodeSet);
  1073.                 }
  1074.                 // lancio questo errore e se presente anche quello con la ricerca notset nodoset.
  1075.                 if(exceptionNodeSet!=null) {
  1076.                     throw new UtilsMultiException(e,exceptionNodeSet);
  1077.                 }
  1078.                 else {
  1079.                     throw e;
  1080.                 }
  1081.             }
  1082.         }
  1083.        
  1084.         if(risultato == null || risultato.isEmpty()){
  1085.             if(exceptionNodeSet!=null){
  1086.                 log.debug("Non sono stati trovati risultati tramite l'invocazione del metodo getStringMatchPattern("+pattern
  1087.                         +") invocato in seguito all'errore dell'invocazione getMatchPattern("+
  1088.                         pattern+",NODESET): "+exceptionNodeSet.getMessage(),exceptionNodeSet);
  1089.                 // lancio questo errore.
  1090.                 // Questo errore puo' avvenire perche' ho provato a fare xpath con nodeset
  1091.                 //throw exceptionNodeSet;
  1092.             }
  1093.         }
  1094.        
  1095.         return risultato;
  1096.     }
  1097. }