AbstractOpenSPCoop2Message_saaj_impl.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.message.soap;

  21. import java.io.OutputStream;
  22. import java.util.ArrayList;
  23. import java.util.Iterator;
  24. import java.util.List;
  25. import java.util.Locale;

  26. import javax.activation.DataHandler;
  27. import javax.xml.namespace.QName;
  28. import javax.xml.soap.AttachmentPart;
  29. import javax.xml.soap.MimeHeaders;
  30. import javax.xml.soap.SOAPBody;
  31. import javax.xml.soap.SOAPElement;
  32. import javax.xml.soap.SOAPEnvelope;
  33. import javax.xml.soap.SOAPException;
  34. import javax.xml.soap.SOAPFactory;
  35. import javax.xml.soap.SOAPFault;
  36. import javax.xml.soap.SOAPHeader;
  37. import javax.xml.soap.SOAPHeaderElement;
  38. import javax.xml.soap.SOAPMessage;
  39. import javax.xml.soap.SOAPPart;
  40. import javax.xml.transform.Source;
  41. import javax.xml.transform.dom.DOMSource;

  42. import org.apache.commons.io.output.CountingOutputStream;
  43. import org.apache.wss4j.common.WSS4JConstants;
  44. import org.openspcoop2.message.ForwardConfig;
  45. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  46. import org.openspcoop2.message.OpenSPCoop2MessageProperties;
  47. import org.openspcoop2.message.constants.Costanti;
  48. import org.openspcoop2.message.constants.MessageType;
  49. import org.openspcoop2.message.exception.MessageException;
  50. import org.openspcoop2.message.exception.MessageNotSupportedException;
  51. import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
  52. import org.openspcoop2.message.soap.reference.AttachmentReference;
  53. import org.openspcoop2.message.soap.reference.ElementReference;
  54. import org.openspcoop2.message.soap.reference.Reference;
  55. import org.openspcoop2.message.xml.MessageDynamicNamespaceContextFactory;
  56. import org.openspcoop2.message.xml.MessageXMLUtils;
  57. import org.openspcoop2.message.xml.XPathExpressionEngine;
  58. import org.openspcoop2.utils.LoggerWrapperFactory;
  59. import org.openspcoop2.utils.dch.DataContentHandlerManager;
  60. import org.openspcoop2.utils.transport.http.ContentTypeUtilities;
  61. import org.openspcoop2.utils.transport.http.HttpConstants;
  62. import org.openspcoop2.utils.xml.AbstractXPathExpressionEngine;
  63. import org.openspcoop2.utils.xml.DynamicNamespaceContext;
  64. import org.openspcoop2.utils.xml.XPathNotFoundException;
  65. import org.openspcoop2.utils.xml.XPathReturnType;
  66. import org.w3c.dom.Element;
  67. import org.w3c.dom.Node;
  68. import org.w3c.dom.NodeList;

  69. /**
  70.  * AbstractXMLBaseOpenSPCoop2Message
  71.  *
  72.  * @author Andrea Poli (apoli@link.it)
  73.  * @author $Author$
  74.  * @version $Rev$, $Date$
  75.  */
  76. public abstract class AbstractOpenSPCoop2Message_saaj_impl extends AbstractBaseOpenSPCoop2SoapMessage {

  77.     private SOAPMessage soapMessage;    
  78.     protected SOAPMessage _getSoapMessage() {
  79.         return this.soapMessage;
  80.     }

  81.     public AbstractOpenSPCoop2Message_saaj_impl(OpenSPCoop2MessageFactory messageFactory, SOAPMessage soapMessage){
  82.         super(messageFactory);
  83.         this.soapMessage = soapMessage;
  84.     }
  85.    
  86.    
  87.     /* Informazioni SOAP (senza costruire il DOM) */
  88.    
  89.     @Override
  90.     public OpenSPCoop2MessageSoapStreamReader getSoapReader() throws MessageException,MessageNotSupportedException {
  91.         //throw new MessageException("NotImplemented; use soap impl");
  92.         return null;
  93.     }
  94.    
  95.    
  96.    
  97.     /* Metodi SOAP */
  98.    
  99.     @Override
  100.     protected SOAPMessage _getSOAPMessage() throws MessageException{
  101.         return this.soapMessage;
  102.     }
  103.    
  104.     @Override
  105.     public SOAPPart getSOAPPart() throws MessageException,MessageNotSupportedException{
  106.         return this.soapMessage.getSOAPPart();
  107.     }
  108.    
  109.     @Override
  110.     public SOAPBody getSOAPBody() throws MessageException,MessageNotSupportedException{
  111.         try{
  112.             return this.soapMessage.getSOAPBody();
  113.         }catch(Exception e){
  114.             throw new MessageException(e.getMessage(),e);
  115.         }
  116.     }
  117.    
  118.     @Override
  119.     public boolean hasSOAPFault() throws MessageException,MessageNotSupportedException{
  120.         SOAPBody body = getSOAPBody();
  121.         return body!=null && body.hasFault();
  122.     }
  123.    
  124.     @Override
  125.     public boolean isSOAPBodyEmpty() throws MessageException,MessageNotSupportedException{
  126.         SOAPBody body = getSOAPBody();
  127.         boolean hasContent = body!=null;
  128.         if(hasContent){
  129.             hasContent = SoapUtils.getFirstNotEmptyChildNode(this.messageFactory, body, false)!=null;
  130.         }
  131.         return !hasContent;
  132.     }
  133.    
  134.     @Override
  135.     public SOAPHeader getSOAPHeader() throws MessageException,MessageNotSupportedException{
  136.         try{
  137.             return this.soapMessage.getSOAPHeader();
  138.         }catch(Exception e){
  139.             throw new MessageException(e.getMessage(),e);
  140.         }
  141.     }
  142.    

  143.    
  144.    
  145.     /* Attachments SOAP */
  146.    
  147.     @Override
  148.     public void addAttachmentPart(AttachmentPart attachmentPart) throws MessageException,MessageNotSupportedException{
  149.         this.soapMessage.addAttachmentPart(attachmentPart);
  150.     }
  151.    
  152.     @Override
  153.     public AttachmentPart createAttachmentPart(DataHandler dataHandler) throws MessageException,MessageNotSupportedException{
  154.         return this.soapMessage.createAttachmentPart(dataHandler);
  155.     }
  156.    
  157.     @Override
  158.     public AttachmentPart createAttachmentPart() throws MessageException,MessageNotSupportedException{
  159.         return this.soapMessage.createAttachmentPart();
  160.     }
  161.    
  162.     @Override
  163.     public boolean hasAttachments() throws MessageException,MessageNotSupportedException{
  164.         return this.soapMessage.countAttachments()>0;
  165.     }
  166.    
  167.     @Override
  168.     public int countAttachments() throws MessageException,MessageNotSupportedException{
  169.         return this.soapMessage.countAttachments();
  170.     }
  171.    
  172.     @Override
  173.     public Iterator<?> getAttachments() throws MessageException,MessageNotSupportedException{
  174.         return this.soapMessage.getAttachments();
  175.     }
  176.    
  177.     @Override
  178.     public Iterator<?> getAttachments(MimeHeaders headers) throws MessageException,MessageNotSupportedException{
  179.         String[] values = headers.getHeader("Content-Id");
  180.         if(values.length > 0 && (!values[0].startsWith("<") || !values[0].endsWith(">"))) {
  181.             headers.removeHeader("Content-Id");
  182.             headers.setHeader("Content-Id", "<" + values[0] + ">");
  183.         }
  184.         return this.soapMessage.getAttachments(headers);
  185.     }
  186.    
  187.     @Override
  188.     public AttachmentPart getAttachment(SOAPElement element) throws MessageException,MessageNotSupportedException{
  189.         try{
  190.             return this.soapMessage.getAttachment(element);
  191.         }catch(Exception e){
  192.             throw new MessageException(e.getMessage(),e);
  193.         }
  194.     }
  195.    
  196.     @Override
  197.     public void removeAllAttachments() throws MessageException,MessageNotSupportedException{
  198.         this.soapMessage.removeAllAttachments();
  199.     }
  200.    
  201.     @Override
  202.     public void removeAttachments(MimeHeaders mhs) throws MessageException,MessageNotSupportedException{
  203.         this.soapMessage.removeAttachments(mhs);
  204.         // Aggiorno il Content-Type se sono finiti gli Attachments.
  205.         if(this.soapMessage.countAttachments() == 0){
  206.             this.setContentType(HttpConstants.CONTENT_TYPE_SOAP_1_1);
  207.         }
  208.     }
  209.    
  210.     @Override
  211.     public void updateAttachmentPart(AttachmentPart ap,DataHandler dh) throws MessageException,MessageNotSupportedException{
  212.         ap.setDataHandler(dh);
  213.     }
  214.    
  215.     @Override
  216.     public void updateAttachmentPart(AttachmentPart ap,byte[]content,String contentType) throws MessageException,MessageNotSupportedException {
  217.         // Se si usa il solo metodo del ramo else, in tomcat si ottiene il seguente errore (con dump abilitato):
  218.         // ... Unable to run the JAXP transformer on a stream [B cannot be cast to javax.xml.transform.Source (sourceException: Error during saving a multipart message)
  219.         try {
  220.             String baseType = ContentTypeUtilities.readBaseTypeFromContentType(contentType);
  221.             if(HttpConstants.CONTENT_TYPE_TEXT_XML.equals(baseType)) {
  222.                 Source streamSource = null;
  223.                 DataContentHandlerManager dchManager = new DataContentHandlerManager(LoggerWrapperFactory.getLogger(AbstractOpenSPCoop2Message_saaj_impl.class));
  224.                 if(dchManager.readMimeTypesContentHandler().containsKey(HttpConstants.CONTENT_TYPE_TEXT_XML)) {
  225.                     // Se è non registrato un content handler per text/xml
  226.                     // succede se dentro l'ear non c'e' il jar mailapi e l'application server non ha caricato il modulo mailapi (es. tramite versione standalone standard)
  227.                     // e si usa il metodo seguente DOMSource si ottiene il seguente errore:
  228.                     // javax.xml.soap.SOAPException: no object DCH for MIME type text/xml
  229.                     //    at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1396) ~[saaj-impl-1.3.28.jar:?]
  230.                     //System.out.println("XML (DOMSource)");
  231.                     streamSource = new DOMSource(MessageXMLUtils.getInstance(this.messageFactory).newElement(content));
  232.                 }
  233.                 else {
  234.                     // Se è registrato un content handler per text/xml
  235.                     // e succede se dentro l'ear c'e' il jar mailapi oppure se l'application server ha caricato il modulo mailapi (es. tramite versione standalone full)
  236.                     // e si usa il metodo seguente StreamSource, si ottiene il seguente errore:
  237.                     //  Unable to run the JAXP transformer on a stream org.xml.sax.SAXParseException; Premature end of file. (sourceException: Error during saving a multipart message)
  238.                     //      com.sun.xml.messaging.saaj.SOAPExceptionImpl: Error during saving a multipart message
  239.                     //        at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1396) ~[saaj-impl-1.3.28.jar:?]
  240.                     //        at org.openspcoop2.message.Message1_1_FIX_Impl.writeTo(Message1_1_FIX_Impl.java:172) ~[openspcoop2_message_BUILD-13516.jar:?]
  241.                     //        at org.openspcoop2.message.OpenSPCoop2Message_11_impl.writeTo
  242.                     //System.out.println("XML (StreamSource)");
  243.                     streamSource = new javax.xml.transform.stream.StreamSource(new java.io.ByteArrayInputStream(content));
  244.                 }
  245.                 ap.setContent(streamSource, contentType);
  246.             }
  247.             else {
  248.                 this.updateAttachmentPart(ap, new DataHandler(content,contentType));
  249.             }
  250.         }catch(Exception e) {
  251.             throw new MessageException(e.getMessage(),e);
  252.         }
  253.     }
  254.    
  255.     @Override
  256.     public void updateAttachmentPart(AttachmentPart ap,String content,String contentType) throws MessageException,MessageNotSupportedException {
  257.         this.updateAttachmentPart(ap, new DataHandler(content,contentType));
  258.     }

  259.    
  260.    
  261.     /* ContentID Attachments SOAP */
  262.    
  263.     @Override
  264.     public String createContentID(String ns) throws MessageException,MessageNotSupportedException{
  265.         return _createContentID(ns);
  266.     }
  267.     protected static String _createContentID(String ns) throws MessageException,MessageNotSupportedException{
  268.         try{
  269.             return "<" + org.apache.cxf.attachment.AttachmentUtil.createContentID(ns) + ">";
  270.         }catch(Exception e){
  271.             throw new MessageException(e.getMessage(),e);
  272.         }
  273.     }
  274.    
  275.    
  276.    
  277.    
  278.    
  279.     /* Trasporto */
  280.    
  281.     @Override
  282.     public OpenSPCoop2MessageProperties getForwardTransportHeader(ForwardConfig forwardConfig) throws MessageException{
  283.         OpenSPCoop2MessageProperties msg = super.getForwardTransportHeader(forwardConfig);
  284.         return new OpenSPCoop2MessageMimeHeaderProperties(this.soapMessage,msg);
  285.     }
  286.    


  287.     /* ContentType */
  288.    
  289.     protected abstract String _super_getContentType();
  290.    
  291.     @Override
  292.     public void updateContentType() throws MessageException {
  293.         try{
  294.             if(countAttachments() > 0){
  295.                 if(saveRequired()) {
  296.                     saveChanges();
  297.                 }
  298.             }
  299.             else {
  300.            
  301.                 if(saveRequired()) {
  302.                    
  303.                     boolean pulizia = false;
  304.                     String contentType = _super_getContentType();
  305.                     if((ContentTypeUtilities.isMtom(contentType)) ){
  306.                         // Bug Fix: OP-375  'Unable to internalize message' con messaggi senza attachments con ContentType 'multipart/related; ...type="application/xop+xml"'
  307.                         //          Capita per i messaggi che contengono un content type multipart e però non sono effettivamente presenti attachments.
  308.                         saveChanges();
  309.                         pulizia = true;
  310.                     }
  311.                     else if((ContentTypeUtilities.isMultipartRelated(contentType)) ){
  312.                         // Bug Fix: OP-678 'Unable to internalize message' con messaggi senza attachments con ContentType 'multipart/related; ...type="text/xml"'
  313.                         //          Capita per i messaggi che contengono un content type multipart e però non sono effettivamente presenti attachments.
  314.                         saveChanges();
  315.                         pulizia = true;
  316.                     }
  317.                    
  318.                     if(pulizia) {
  319.                         try {
  320.                             javax.mail.internet.ContentType ctObj = new javax.mail.internet.ContentType(contentType);
  321.                            
  322.                             // Bug Fix: OP-909
  323.                             // Rimane il tipo 'Multipart-Type' come Content-Type in caso di messaggio 'MTOM' senza allegati.
  324.                             String contentTypeInternal = ContentTypeUtilities.getInternalMultipartContentType(contentType);
  325.                             javax.mail.internet.ContentType ctObjInternal = new javax.mail.internet.ContentType(contentTypeInternal);
  326.                             ctObj.setPrimaryType(ctObjInternal.getPrimaryType());
  327.                             ctObj.setSubType(ctObjInternal.getSubType());
  328.                            
  329.                             String type = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE);
  330.                             if(type!=null && !type.equals("")) {
  331.                                 ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE);
  332.                             }
  333.                            
  334.                             String boundary = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_BOUNDARY);
  335.                             if(boundary!=null && !boundary.equals("")) {
  336.                                 ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_BOUNDARY);
  337.                             }
  338.                            
  339.                             String start = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START);
  340.                             if(start!=null && !start.equals("")) {
  341.                                 ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START);
  342.                             }
  343.                            
  344.                             String startInfo = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO);
  345.                             if(startInfo!=null && !startInfo.equals("")) {
  346.                                 ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO);
  347.                             }
  348.                            
  349.                             this.setContentType(ctObj.toString());
  350.                            
  351.                         }catch(Throwable t) {
  352.                             System.err.println("Pulizia messaggio Multipart normalizzato senza attachment non riuscita: "+t.getMessage());
  353.                             t.printStackTrace(System.err);
  354.                         }
  355.                     }
  356.                 }
  357.                
  358.             }
  359.         }catch(Exception e){
  360.             throw new MessageException(e.getMessage(),e);
  361.         }
  362.     }


  363.    
  364.     /* WriteTo e Save */
  365.    
  366.     @Override
  367.     public boolean isContentBuilded() {
  368.         return true; // e' insito nel costruttore
  369.     }
  370.    
  371.     @Override
  372.     public void writeTo(OutputStream os, boolean consume) throws MessageException{
  373.         try{
  374.             CountingOutputStream cos = new CountingOutputStream(os);
  375.             this.soapMessage.writeTo(cos);
  376.             this.outgoingsize = cos.getByteCount();
  377.         }catch(Exception e){
  378.             throw new MessageException(e.getMessage(),e);
  379.         }
  380.     }
  381.    
  382.     @Override
  383.     public void saveChanges() throws MessageException{
  384.         try{
  385.             this.soapMessage.saveChanges();
  386.         }catch(Exception e){
  387.             throw new MessageException(e.getMessage(),e);
  388.         }
  389.     }
  390.    
  391.     @Override
  392.     public boolean saveRequired(){
  393.         return this.soapMessage.saveRequired();
  394.     }
  395.    
  396.    
  397.    
  398.     /* SOAP Utilities */
  399.    
  400.     @Override
  401.     public Element getFirstChildElement(SOAPElement element) throws MessageException,MessageNotSupportedException {
  402.         return _getFirstChildElement(element);
  403.     }
  404.     protected static Element _getFirstChildElement(SOAPElement element) throws MessageException,MessageNotSupportedException {
  405.         Element firstElement = null;
  406.         NodeList nl = element.getChildNodes();
  407.         if(nl!=null) {
  408.             for (int i = 0; i < nl.getLength(); i++) {
  409.                 Node tmp = nl.item(i);
  410.                 if(tmp instanceof Element) {
  411.                     firstElement = (Element) tmp;
  412.                     break;
  413.                 }
  414.             }
  415.         }
  416.         /**
  417.          * Usato anzi 'element.getChildNodes()'; il metodo getChildElements, in un soap body faceva perdere tutti gli altri elementi nella validazione dei contenuti usando il dynamic namespace context
  418.          * Iterator<?> it = element.getChildElements();
  419.         while (it.hasNext() && firstElement==null){
  420.             Node tmp = (Node) it.next();
  421.             if(tmp instanceof Element) firstElement = (Element) tmp;
  422.         }*/
  423.         return firstElement;
  424.     }
  425.    
  426.     @Override
  427.     public SOAPElement createSOAPElement(byte[] bytes) throws MessageException,MessageNotSupportedException {
  428.         return _createSOAPElement(bytes, this.getMessageType(), this.messageFactory);
  429.     }
  430.     protected static SOAPElement _createSOAPElement(byte[] bytes, MessageType messageType, OpenSPCoop2MessageFactory messageFactory) throws MessageException,MessageNotSupportedException {
  431.         try{
  432.             SOAPFactory soapFactory = null;
  433.             if(MessageType.SOAP_11.equals(messageType)){
  434.                 soapFactory = messageFactory.getSoapFactory11();
  435.             }
  436.             else if(MessageType.SOAP_12.equals(messageType)){
  437.                 soapFactory = messageFactory.getSoapFactory12();
  438.             }
  439.             else{
  440.                 throw new MessageException("MessageType ["+messageType+"] not supported");
  441.             }
  442.             return soapFactory.createElement(MessageXMLUtils.getInstance(messageFactory).newElement(bytes));
  443.         }catch(Exception e){
  444.             throw new MessageException(e.getMessage(),e);
  445.         }
  446.     }
  447.    
  448.     @Override
  449.     public SOAPHeaderElement newSOAPHeaderElement(SOAPHeader hdr,QName name) throws MessageException,MessageNotSupportedException {
  450.         return _newSOAPHeaderElement(hdr,name);
  451.     }
  452.     protected static SOAPHeaderElement _newSOAPHeaderElement(SOAPHeader hdr,QName name) throws MessageException,MessageNotSupportedException {
  453.         try{
  454.             SOAPHeaderElement newHeader =   hdr.addHeaderElement(name);
  455.             return newHeader;
  456.         }catch(Exception e){
  457.             throw new MessageException(e.getMessage(),e);
  458.         }
  459.     }
  460.    
  461.     @Override
  462.     public void addHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
  463.         _addHeaderElement(hdr, hdrElement);
  464.     }
  465.     protected static void _addHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
  466.         try{
  467.             hdr.addChildElement(hdrElement);
  468.         }catch(Exception e){
  469.             throw new MessageException(e.getMessage(),e);
  470.         }
  471.     }
  472.    
  473.     @Override
  474.     public void removeHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
  475.         _removeHeaderElement(hdr, hdrElement);
  476.     }
  477.     protected static void _removeHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
  478.         try{
  479.             hdr.removeChild(hdrElement);
  480.         }catch(Exception e){
  481.             throw new MessageException(e.getMessage(),e);
  482.         }
  483.     }
  484.    
  485.     @Override
  486.     public void setFaultCode(SOAPFault fault, SOAPFaultCode code,
  487.             QName eccezioneName) throws MessageException,MessageNotSupportedException {
  488.         _setFaultCode(fault, code, eccezioneName);
  489.     }
  490.     protected static void _setFaultCode(SOAPFault fault, SOAPFaultCode code,
  491.             QName eccezioneName) throws MessageException,MessageNotSupportedException {
  492.         try{
  493.             fault.setFaultCode(eccezioneName);
  494.         }catch(Exception e){
  495.             throw new MessageException(e.getMessage(),e);
  496.         }
  497.     }
  498.    
  499.     @Override
  500.     public void setFaultString(SOAPFault fault, String message) throws MessageException,MessageNotSupportedException{
  501.         _setFaultString(fault, message);
  502.     }
  503.     protected static void _setFaultString(SOAPFault fault, String message) throws MessageException,MessageNotSupportedException{
  504.         try{
  505.             SoapUtils.setFaultString(fault, message, null);
  506.         }catch(Exception e){
  507.             throw new MessageException(e.getMessage(),e);
  508.         }
  509.     }
  510.     @Override
  511.     public void setFaultString(SOAPFault fault, String message, Locale locale) throws MessageException,MessageNotSupportedException{
  512.         _setFaultString(fault, message, locale);
  513.     }
  514.     protected static void _setFaultString(SOAPFault fault, String message, Locale locale) throws MessageException,MessageNotSupportedException{
  515.         try{
  516.             SoapUtils.setFaultString(fault, message, locale);
  517.         }catch(Exception e){
  518.             throw new MessageException(e.getMessage(),e);
  519.         }
  520.     }
  521.    
  522.    
  523.    
  524.     /* Ws Security */
  525.    
  526.     private SOAPPart getSOAPPartForSearchWSSecurity(){
  527.         return this.soapMessage.getSOAPPart();
  528.     }
  529.    
  530.     @Override
  531.     public List<Reference> getWSSDirtyElements(String actor, boolean mustUnderstand) throws MessageException,MessageNotSupportedException {
  532.        
  533.         try{
  534.        
  535.             List<Reference> references = new ArrayList<Reference>();
  536.            
  537.             // Prendo il security Header di mia competenza
  538.             SOAPElement security = (SOAPElement) WSSecurityUtils.getSecurityHeader(this.getSOAPPartForSearchWSSecurity(),this.messageType, actor,
  539.                     this.isThrowExceptionIfFoundMoreSecurityHeader());
  540.            
  541.             //TODO verificare se actor==null && mustUnderstand==false?
  542.             if(security!=null){
  543.                 // Prendo i riferimenti agli elementi cifrati
  544.                 Iterator<?> it = security.getChildElements(new QName(WSS4JConstants.ENC_NS, WSS4JConstants.ENC_KEY_LN));
  545.                 if(it.hasNext()){
  546.                     SOAPElement encryptedKey = (SOAPElement) it.next();
  547.                     SOAPElement referenceList = (SOAPElement) encryptedKey.getChildElements(new QName(WSS4JConstants.ENC_NS, WSS4JConstants.REF_LIST_LN)).next();
  548.                     List<SOAPElement> referenceListElements = SoapUtils.getNotEmptyChildSOAPElement(referenceList);
  549.                     for (int i = 0; i < referenceListElements.size(); i++) {
  550.                         String referenceWithSharp = referenceListElements.get(i).getAttributeValue(new QName("URI"));
  551.                         // Il riferimento presenta un # prima dell'identificativo se e' un elemento o cid: se e' un attachment
  552.                         if(referenceWithSharp.startsWith("#")){
  553.                             String reference = referenceWithSharp.substring(1);
  554.                             // Vado a vedere se ' cifrato {Content} o {Element}
  555.                             SOAPElement encryptedElement = (SOAPElement) org.apache.wss4j.common.util.XMLUtils.findElementById(this.getSOAPPartForSearchWSSecurity().getEnvelope(), reference, true);
  556.                             if(encryptedElement==null){
  557.                                 throw new SOAPException("Element with 'Id' attribute value ("+referenceWithSharp+") not found "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
  558.                             }
  559.                            
  560.                             // Verifico se sto cifrando un attachment
  561.                             QName qName = new QName(WSS4JConstants.ENC_NS, "CipherData");
  562.                             Iterator<?> childElements = encryptedElement.getChildElements(qName);
  563.                             if(childElements!=null && childElements.hasNext()){
  564.                                
  565.                                 QName qNameReference = new QName(WSS4JConstants.ENC_NS, "CipherReference");
  566.                                 Iterator<?> childElementsReference = ((SOAPElement)childElements.next()).getChildElements(qNameReference);
  567.                                 if(childElementsReference!=null && childElementsReference.hasNext()){
  568.                                    
  569.                                     // Attachment cifrato
  570.                                     String referenceAttach = ((SOAPElement) childElementsReference.next()).getAttributeValue(new QName("URI"));
  571.                                     if(referenceAttach.startsWith("cid:")){
  572.                                         String referenceCID = referenceAttach.substring(4);
  573.                                         references.add(new AttachmentReference (AttachmentReference.TYPE_ENCRYPT_ATTACHMENT, referenceCID));
  574.                                     }else{
  575.                                         throw new SOAPException("Element 'CipherReference' with attribute 'cid' wrong "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
  576.                                     }
  577.                                    
  578.                                 }else{
  579.                                    
  580.                                     // Elemento cifrato
  581.                                     if(encryptedElement.getAttributeNS(null, "Type").equals(WSS4JConstants.ENC_NS + "Content"))
  582.                                         references.add(new ElementReference(encryptedElement.getParentElement(), ElementReference.TYPE_ENCRYPT_CONTENT, reference));
  583.                                     else
  584.                                         references.add(new ElementReference (encryptedElement.getParentElement(), ElementReference.TYPE_ENCRYPT_ELEMENT, reference));  
  585.                                 }
  586.                             }
  587.                             else{
  588.                                 throw new SOAPException("Element 'CipherData' not found "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
  589.                             }
  590.                            
  591.                         }
  592.                     }
  593.                 }
  594.                
  595.                 // Prendo i riferimenti agli elementi firmati
  596.                 it = security.getChildElements(new QName(WSS4JConstants.SIG_NS, WSS4JConstants.SIG_LN));
  597.                 if(it.hasNext()){
  598.                     SOAPElement signature = (SOAPElement) it.next();
  599.                     SOAPElement signatureInfo = (SOAPElement) signature.getChildElements(new QName(WSS4JConstants.SIG_NS, "SignedInfo")).next();
  600.                     Iterator<?> referenceIterator = signatureInfo.getChildElements(new QName(WSS4JConstants.SIG_NS, "Reference"));
  601.                     while (referenceIterator.hasNext()) {
  602.                         String referenceWithSharp = ((SOAPElement) referenceIterator.next()).getAttributeValue(new QName("URI"));
  603.                         // Il riferimento presenta un # prima dell'identificativo se e' un elemento o cid: se e' un attachment
  604.                         if(referenceWithSharp.startsWith("#")){
  605.                             String reference = referenceWithSharp.substring(1);
  606.                            
  607.                             SOAPEnvelope soapEnvelope = this.getSOAPPartForSearchWSSecurity().getEnvelope();
  608.                            
  609.                             SOAPElement signedElement = (SOAPElement) org.apache.wss4j.common.util.XMLUtils.findElementById(soapEnvelope, reference, true);
  610.                             if(signedElement==null){
  611.                                
  612.                                 // Provo a vedere se l'elemento firmato e' una Assertion
  613.                                
  614.                                 DynamicNamespaceContext dnc = null;
  615.                                 if(MessageType.SOAP_11.equals(this.getMessageType())) {
  616.                                     dnc = MessageDynamicNamespaceContextFactory.getInstance(this.messageFactory).getNamespaceContextFromSoapEnvelope11(soapEnvelope);
  617.                                 } else {
  618.                                     dnc = MessageDynamicNamespaceContextFactory.getInstance(this.messageFactory).getNamespaceContextFromSoapEnvelope12(soapEnvelope);
  619.                                 }
  620.                                
  621.                                 AbstractXPathExpressionEngine xpathExpressionEngine = new XPathExpressionEngine(this.messageFactory);
  622.                                
  623.                                 try {
  624.                                     String xpath = Costanti.XPATH_SAML_20_ASSERTION + "[@"+Costanti.SAML_20_ASSERTION_ID+"='"+reference+"']";
  625.                                     Object o = xpathExpressionEngine.getMatchPattern(security, dnc, xpath, XPathReturnType.NODE);
  626.                                     signedElement = (SOAPElement) o;
  627.                                 } catch(XPathNotFoundException e) {}
  628.                                
  629.                                 if(signedElement==null){
  630.                                     try {
  631.                                         String xpath = Costanti.XPATH_SAML_11_ASSERTION + "[@"+Costanti.SAML_11_ASSERTION_ID+"='"+reference+"']";
  632.                                         Object o = xpathExpressionEngine.getMatchPattern(security, dnc, xpath, XPathReturnType.NODE);
  633.                                         signedElement = (SOAPElement) o;
  634.                                     } catch(XPathNotFoundException e) {}
  635.                                 }
  636.                                
  637.                                 if(signedElement==null){
  638.                                     throw new SOAPException("Element with 'Id' attribute value ("+referenceWithSharp+") not found "+Costanti.FIND_ERROR_SIGNATURE_REFERENCES);
  639.                                 }
  640.                             }
  641.                             references.add(new ElementReference (signedElement, ElementReference.TYPE_SIGNATURE, reference));
  642.                         } else if(referenceWithSharp.startsWith("cid:")){
  643.                             String reference = referenceWithSharp.substring(4);
  644.                             references.add(new AttachmentReference(AttachmentReference.TYPE_SIGN_ATTACHMENT, reference));
  645.                         }
  646.                     }
  647.                 }
  648.             }
  649.    
  650.             return references;
  651.            
  652.         }catch(Exception e){
  653.             throw new MessageException(e.getMessage(),e);
  654.         }
  655.     }
  656.    

  657.     @Override
  658.     public void cleanWSSDirtyElements(String actor, boolean mustUnderstand, List<Reference> references, boolean detachHeaderWSSecurity, boolean removeAllIdRef) throws MessageException,MessageNotSupportedException {
  659.        
  660.         try{
  661.        
  662.             // Prendo il security Header di mia competenza
  663.             SOAPElement security = (SOAPElement) WSSecurityUtils.getSecurityHeader(this.getSOAPPartForSearchWSSecurity(),this.messageType, actor,
  664.                     this.isThrowExceptionIfFoundMoreSecurityHeader());
  665.            
  666.             // Rimuovo l'header Security
  667.             if(detachHeaderWSSecurity){
  668.                 security.detachNode();
  669.             }
  670.            
  671.             boolean found;
  672.            
  673.             // Pulisco i nodi sporchi
  674.             for(int i=0; i<references.size(); i++){
  675.                 Reference reference = references.get(i);
  676.                 if(reference instanceof ElementReference) {
  677.                     SOAPElement elementToClean = ((ElementReference)reference).getElement();
  678.                     switch (reference.getType()) {
  679.                     case ElementReference.TYPE_SIGNATURE:
  680.                         // Devo vedere se altri hanno firmato l'elemento ed in tal caso lasciar fare l'id ed il namespace
  681.                         found = false;
  682.                         NodeList securities = this.getSOAPHeader().getElementsByTagNameNS(WSS4JConstants.WSSE_NS, WSS4JConstants.WSSE_LN);
  683.                         for(int s=0; s<securities.getLength(); s++){
  684.                             security = (SOAPElement) securities.item(s);
  685.                             // Prendo i riferimenti agli elementi firmati
  686.                             Iterator<?>  it = security.getChildElements(new QName(WSS4JConstants.SIG_NS, WSS4JConstants.SIG_LN));
  687.                             if(it.hasNext()){
  688.                                 SOAPElement signature = (SOAPElement) it.next();
  689.                                 SOAPElement signatureInfo = (SOAPElement) signature.getChildElements(new QName(WSS4JConstants.SIG_NS, "SignedInfo")).next();
  690.                                 Iterator<?> referenceIterator = signatureInfo.getChildElements(new QName(WSS4JConstants.SIG_NS, "Reference"));
  691.                                 while (referenceIterator.hasNext()) {
  692.                                     String referenceWithSharp = ((SOAPElement) referenceIterator.next()).getAttributeValue(new QName("URI"));
  693.                                     if(reference.getReference().equals(referenceWithSharp.substring(1))) {
  694.                                         found = true;
  695.                                     }
  696.                                 }
  697.                             }
  698.                         }
  699.                         if(!found) {
  700.                            
  701.                             boolean removeIdRefSignature = false;
  702.                             if(removeAllIdRef){
  703.                                 // alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
  704.                                 // Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
  705.                                 removeIdRefSignature = true;
  706.                                 elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  707.                             }
  708.                             else{
  709.                                 String valoreRefSignature = elementToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
  710.                                 // fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
  711.                                 //System.out.println("CHECK TYPE_SIGNATURE ["+valoreRefSignature+"] ["+reference.getReference()+"]");
  712.                                 if(valoreRefSignature!=null && valoreRefSignature.equals(reference.getReference())){
  713.                                     removeIdRefSignature = true;
  714.                                 }
  715.                                
  716.                                 if(removeIdRefSignature){
  717.                                     elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  718.                                 }
  719.                             }
  720.                                
  721.                             List<String> prefixesToRemoveContent = new ArrayList<>();
  722.                             Iterator<?> prefixes = elementToClean.getNamespacePrefixes();
  723.                             while(prefixes.hasNext()){
  724.                                 String prefix = (String) prefixes.next();
  725.                                 String namespace = elementToClean.getNamespaceURI(prefix);
  726.                                 if(namespace.equals(WSS4JConstants.WSU_NS)) {
  727.                                     if(removeIdRefSignature){
  728.                                         prefixesToRemoveContent.add(prefix);
  729.                                     }
  730.                                 }
  731.                             }
  732.                             for(int y=0; y<prefixesToRemoveContent.size(); y++)
  733.                                 elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
  734.                         }
  735.                         break;
  736.        
  737.                     case ElementReference.TYPE_ENCRYPT_CONTENT:
  738.                         List<String> prefixesToRemoveContent = new ArrayList<>();
  739.                         Iterator<?> prefixesContent = elementToClean.getNamespacePrefixes();
  740.                         while(prefixesContent.hasNext()){
  741.                             String prefix = (String) prefixesContent.next();
  742.                             String namespace = elementToClean.getNamespaceURI(prefix);
  743.                             if(namespace.equals(WSS4JConstants.ENC_NS) ||  namespace.equals(elementToClean.getNamespaceURI(prefix))){
  744.                                 prefixesToRemoveContent.add(prefix);
  745.                             }
  746.                         }
  747.                         for(int y=0; y<prefixesToRemoveContent.size(); y++)
  748.                             elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
  749.                        
  750.                         boolean removeIdRefEncContent = false;
  751.                         if(removeAllIdRef){
  752.                             // alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
  753.                             // Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
  754.                             removeIdRefEncContent = true;
  755.                             elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  756.                         }
  757.                         else{
  758.                             String valoreRefEncContent = elementToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
  759.                             // fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
  760.                             //System.out.println("CHECK TYPE_ENCRYPT_CONTENT ["+valoreRefEncContent+"] ["+reference.getReference()+"]");
  761.                             if(valoreRefEncContent!=null && valoreRefEncContent.equals(reference.getReference())){
  762.                                 removeIdRefEncContent = true;
  763.                             }
  764.                            
  765.                             if(removeIdRefEncContent){
  766.                                 elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  767.                             }
  768.                         }
  769.                            
  770.                         prefixesToRemoveContent = new ArrayList<>();
  771.                         prefixesContent = elementToClean.getNamespacePrefixes();
  772.                         while(prefixesContent.hasNext()){
  773.                             String prefix = (String) prefixesContent.next();
  774.                             String namespace = elementToClean.getNamespaceURI(prefix);
  775.                             if(namespace.equals(WSS4JConstants.WSU_NS)) {
  776.                                 if(removeIdRefEncContent){
  777.                                     prefixesToRemoveContent.add(prefix);
  778.                                 }
  779.                             }
  780.                         }
  781.                         for(int y=0; y<prefixesToRemoveContent.size(); y++)
  782.                             elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
  783.                         break;
  784.                        
  785.                     case ElementReference.TYPE_ENCRYPT_ELEMENT:
  786.                         // Questo codice si occupa di pulire la "sporcizia" wss presente comunque nel elemento cifrato e decifrato.
  787.                         // Poiche' non c'e' modo, esaminando il messaggio cifrato, di identificare (nome e namespace da decifrare) l'elemento cifrato per intero, si e' scelto di tenersi traccia del padre,
  788.                         // e a questo punto di ripulire tutti i figli che contengono sporcizia.
  789.                         // Eventuali figli cifrati in modalita' 'content' rientreranno comunque anche in questa casistica.
  790.                         Iterator<?> childrenToClean =  elementToClean.getChildElements();
  791.                         while(childrenToClean.hasNext()) {
  792.                             Object next = childrenToClean.next();
  793.                             if(next instanceof SOAPElement) {
  794.                                 SOAPElement childToClean = (SOAPElement) next;
  795.                                 List<String> prefixesToRemoveElement = new ArrayList<>();
  796.                                 Iterator<?> prefixesElement = childToClean.getNamespacePrefixes();
  797.                                 while(prefixesElement.hasNext()){
  798.                                     String prefix = (String) prefixesElement.next();
  799.                                     String namespace = childToClean.getNamespaceURI(prefix);
  800.                                     if(namespace.equals(WSS4JConstants.WSU_NS)){
  801.                                         prefixesToRemoveElement.add(prefix);
  802.                                     }
  803.                                 }
  804.                                 for(int y=0; y<prefixesToRemoveElement.size(); y++)
  805.                                     childToClean.removeNamespaceDeclaration(prefixesToRemoveElement.get(y));
  806.                                
  807.                                 boolean removeIdRefEncElement = false;
  808.                                 if(removeAllIdRef){
  809.                                     // alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
  810.                                     // Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
  811.                                     removeIdRefEncContent = true;
  812.                                     childToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  813.                                 }
  814.                                 else{
  815.                                     String valoreRefEncElement = childToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
  816.                                     // fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
  817.                                     //System.out.println("CHECK TYPE_ENCRYPT_ELEMENT ["+valoreRefEncElement+"] ["+reference.getReference()+"]");
  818.                                     if(valoreRefEncElement!=null && valoreRefEncElement.equals(reference.getReference())){
  819.                                         removeIdRefEncElement = true;
  820.                                     }
  821.                                    
  822.                                     if(removeIdRefEncElement){
  823.                                         childToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
  824.                                     }
  825.                                 }
  826.                                    
  827.                                 prefixesToRemoveElement = new ArrayList<>();
  828.                                 prefixesElement = childToClean.getNamespacePrefixes();
  829.                                 while(prefixesElement.hasNext()){
  830.                                     String prefix = (String) prefixesElement.next();
  831.                                     String namespace = childToClean.getNamespaceURI(prefix);
  832.                                     if(namespace.equals(WSS4JConstants.WSU_NS)) {
  833.                                         if(removeIdRefEncElement){
  834.                                             prefixesToRemoveElement.add(prefix);
  835.                                         }
  836.                                     }
  837.                                 }
  838.                                 for(int y=0; y<prefixesToRemoveElement.size(); y++)
  839.                                     childToClean.removeNamespaceDeclaration(prefixesToRemoveElement.get(y));
  840.                             }
  841.                         }
  842.                         break;
  843.                        
  844.                     default:
  845.                         break;
  846.                     }
  847.                 }
  848.             }
  849.            
  850.         }catch(Exception e){
  851.             throw new MessageException(e.getMessage(),e);
  852.         }
  853.     }

  854.    
  855.     /* Ws Security (SoapBox) */
  856.    
  857.     @Override
  858.     public String getEncryptedDataHeaderBlockClass() {
  859.         return _getEncryptedDataHeaderBlockClass();
  860.     }
  861.     protected static String _getEncryptedDataHeaderBlockClass() {
  862.         return "com.sun.xml.wss.core.EncryptedDataHeaderBlock"; // usare la stringa per GPL clean
  863.     }

  864.     @Override
  865.     public String getProcessPartialEncryptedMessageClass() {
  866.         return _getProcessPartialEncryptedMessageClass();
  867.     }
  868.     protected static String _getProcessPartialEncryptedMessageClass() {
  869.         return "org.openspcoop2.security.message.soapbox.ProcessPartialEncryptedMessage";
  870.     }

  871.     @Override
  872.     public String getSignPartialMessageProcessorClass() {
  873.         return _getSignPartialMessageProcessorClass();
  874.     }
  875.     protected static String _getSignPartialMessageProcessorClass() {
  876.         return "org.openspcoop2.security.message.soapbox.SignPartialMessageProcessor";
  877.     }
  878.    
  879.    
  880. }