MTOMUtilities.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.mtom;

  21. import java.io.ByteArrayInputStream;
  22. import java.util.ArrayList;
  23. import java.util.Iterator;
  24. import java.util.List;

  25. //import javax.mail.internet.ContentType;
  26. import com.sun.xml.messaging.saaj.packaging.mime.internet.ContentType;
  27. import javax.xml.namespace.QName;
  28. import javax.xml.soap.AttachmentPart;
  29. import javax.xml.soap.MimeHeaders;

  30. import org.openspcoop2.message.OpenSPCoop2Message;
  31. import org.openspcoop2.message.OpenSPCoop2MessageFactory;
  32. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  33. import org.openspcoop2.message.constants.MessageType;
  34. import org.openspcoop2.message.exception.MessageException;
  35. import org.openspcoop2.message.exception.MessageNotSupportedException;
  36. import org.openspcoop2.message.soap.SoapUtils;
  37. import org.openspcoop2.message.xml.XPathExpressionEngine;
  38. import org.openspcoop2.utils.Utilities;
  39. import org.openspcoop2.utils.io.Base64Utilities;
  40. import org.openspcoop2.utils.transport.http.ContentTypeUtilities;
  41. import org.openspcoop2.utils.transport.http.HttpConstants;
  42. import org.openspcoop2.utils.xml.AbstractXPathExpressionEngine;
  43. import org.openspcoop2.utils.xml.DynamicNamespaceContext;
  44. import org.openspcoop2.utils.xml.XPathNotFoundException;
  45. import org.openspcoop2.utils.xml.XPathReturnType;
  46. import org.w3c.dom.Document;
  47. import org.w3c.dom.Element;
  48. import org.w3c.dom.NamedNodeMap;
  49. import org.w3c.dom.Node;
  50. import org.w3c.dom.NodeList;

  51. /**
  52.  * MTOMUtilities
  53.  *
  54.  * @author Andrea Poli (apoli@link.it)
  55.  * @author $Author$
  56.  * @version $Rev$, $Date$
  57.  */
  58. public class MTOMUtilities {
  59.    
  60.     public static boolean isMtom(String cType) throws MessageException{
  61.         try{
  62.             return ContentTypeUtilities.isMtom(cType);
  63.         }catch(Exception e){
  64.             throw new MessageException(e.getMessage(),e);
  65.         }
  66.     }
  67.    
  68.    
  69.     public static String readInternalMultipartMtomContentType(String contentType) throws MessageException{
  70.         try{
  71.             return readInternalMultipartMtomContentType(new ContentType(contentType));
  72.         }
  73.         catch(MessageException e){
  74.             throw e;
  75.         }
  76.         catch(Exception e){
  77.             throw new MessageException(e.getMessage(),e);
  78.         }
  79.     }
  80.     public static String readInternalMultipartMtomContentType(ContentType contentType) throws MessageException{
  81.         try{
  82.             return ContentTypeUtilities.readInternalMultipartMtomContentType(contentType);
  83.         }
  84.         catch(Exception e){
  85.             throw new MessageException(e.getMessage(),e);
  86.         }
  87.     }
  88.    
  89.     public static List<MtomXomReference> unpackaging(OpenSPCoop2Message msgParam, boolean fast, boolean body) throws MessageException, MessageNotSupportedException{
  90.        
  91.         if(!MessageType.SOAP_11.equals(msgParam.getMessageType()) && !MessageType.SOAP_12.equals(msgParam.getMessageType())){
  92.             throw MessageNotSupportedException.newMessageNotSupportedException(msgParam.getMessageType());
  93.         }
  94.         OpenSPCoop2SoapMessage message = msgParam.castAsSoap();
  95.        
  96.         try{
  97.             List<MtomXomReference> list = new ArrayList<MtomXomReference>();
  98.            
  99.             Element element = null;
  100.             if(body){
  101.                 element = message.getSOAPBody();
  102.             }
  103.             else{
  104.                 element = message.getSOAPPart().getEnvelope();
  105.             }
  106.             if(element==null){
  107.                 return list;
  108.             }
  109.            
  110.             boolean restoredXomReference = false;
  111.            
  112.             AbstractXPathExpressionEngine xpathEngine = new XPathExpressionEngine(msgParam.getFactory());
  113.             DynamicNamespaceContext dnc = org.openspcoop2.message.xml.MessageDynamicNamespaceContextFactory.getInstance(msgParam.getFactory()).getNamespaceContext(element);
  114.             Object oNode = null;
  115.             try{
  116.                 oNode = xpathEngine.getMatchPattern(element, dnc, org.openspcoop2.message.soap.mtom.Costanti.MTOM_XOP_REFERENCES, XPathReturnType.NODESET);
  117.             }catch(XPathNotFoundException notFound){}
  118.             if(oNode==null){
  119.                 // non esistono xom reference
  120.                 return list;
  121.             }
  122.             if( !(oNode instanceof NodeList) ){
  123.                 throw new MessageException("XpathEngine (expr:"+org.openspcoop2.message.soap.mtom.Costanti.MTOM_XOP_REFERENCES+") return wrong type (expected: "+
  124.                         NodeList.class.getName()+"): "+oNode.getClass().getName());
  125.             }
  126.             NodeList nodeList = (NodeList) oNode;
  127.             //System.out.println("Ritornato: size: "+nodeList.getLength());
  128.             for (int i = 0; i < nodeList.getLength(); i++) {
  129.                
  130.                 // xomReference
  131.                 Node xomReference = nodeList.item(i);
  132.                 if(xomReference.getAttributes()==null || xomReference.getAttributes().getLength()<=0){
  133.                     throw new MessageException("Found XOM Reference without attributes ('"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' attribute required)");
  134.                 }
  135.                 Node xomHref = xomReference.getAttributes().getNamedItem(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF);
  136.                 if(xomHref == null){
  137.                     throw new MessageException("Found XOM Reference without attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"'");
  138.                 }
  139.                 String contentId = xomHref.getNodeValue();
  140.                 if(contentId == null){
  141.                     throw new MessageException("Found XOM Reference with attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' without value?");
  142.                 }
  143.                 if(contentId.startsWith(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE)){
  144.                     contentId = contentId.substring(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE.length());
  145.                 }
  146.                 MimeHeaders mhs = new MimeHeaders();
  147.                 mhs.addHeader(HttpConstants.CONTENT_ID, contentId);
  148.                 Iterator<?> itAttachments = message.getAttachments(mhs);
  149.                 if(itAttachments == null || itAttachments.hasNext()==false){
  150.                     throw new MessageException("Found XOM Reference with attribute ["+
  151.                             org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but the message hasn't attachments");
  152.                 }
  153.                 AttachmentPart ap = null;
  154.                 while (itAttachments.hasNext()) {
  155.                     if(ap!=null){
  156.                         throw new MessageException("Found XOM Reference with attribute ["+
  157.                                 org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but exists more than one attachment with same id");
  158.                     }
  159.                     ap = (AttachmentPart) itAttachments.next();
  160.                 }
  161.                 if(ap==null){
  162.                     throw new MessageException("Found XOM Reference with attribute ["+
  163.                             org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but not exists attachment with same id");
  164.                 }
  165.        
  166.                
  167.                 // base64Element
  168.                 Node elementBase64Binary = xomReference.getParentNode();
  169.                 if(elementBase64Binary==null){
  170.                     throw new MessageException("Found XOM Reference without parent node?");
  171.                 }
  172.                 QName qname = new QName(elementBase64Binary.getNamespaceURI(), elementBase64Binary.getLocalName());
  173.                 //System.out.println("Found Element ["+qname.toString()+"]");
  174.                
  175.        
  176.                 // unpackaging
  177.                 String base64Binary = null;
  178.                 if(fast){
  179.                     // fast unpackaging (for validation)
  180.                     base64Binary = Base64Utilities.encodeAsString("FAST".getBytes());
  181.                 }else{
  182.                     base64Binary = Utilities.getAsByteArrayOuputStream(ap.getBase64Content()).toString();
  183.                     message.removeAttachments(mhs);
  184.                     restoredXomReference = true;
  185.                 }
  186.                 elementBase64Binary.removeChild(xomReference);
  187.                 elementBase64Binary.setTextContent(base64Binary);
  188.                
  189.                
  190.                 // add reference
  191.                 MtomXomReference reference = new MtomXomReference();
  192.                 reference.setNodeName(qname);
  193.                 reference.setXomReference(xomReference);
  194.                 reference.setNode(elementBase64Binary);
  195.                 reference.setContentId(contentId);
  196.                 list.add(reference);
  197.             }
  198.            
  199.            
  200.             if(restoredXomReference){
  201.                
  202.                 message.removeContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE);
  203.                 message.removeContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO);
  204.                
  205.                 if(message.countAttachments()>0){
  206.                     // esistono altri attachments "originali" non derivati dalla serializzazione mtom
  207.                     if(MessageType.SOAP_11.equals(message.getMessageType())){
  208.                         message.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE, HttpConstants.CONTENT_TYPE_SOAP_1_1);
  209.                     }
  210.                     else if(MessageType.SOAP_12.equals(message.getMessageType())){
  211.                         message.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE, HttpConstants.CONTENT_TYPE_SOAP_1_2);
  212.                     }
  213.                 }
  214.                 else {
  215.                    
  216.                     ContentType cType = null;
  217.                     if(MessageType.SOAP_11.equals(message.getMessageType())){
  218.                         cType = new ContentType(HttpConstants.CONTENT_TYPE_SOAP_1_1);
  219.                     }
  220.                     else if(MessageType.SOAP_12.equals(message.getMessageType())){
  221.                         cType = new ContentType(HttpConstants.CONTENT_TYPE_SOAP_1_2);
  222.                     }
  223.                    
  224.                     String charsetParam =  ContentTypeUtilities.readCharsetFromContentType(message.getContentType());
  225.                     if(charsetParam!=null && !"".equals(charsetParam)) {
  226.                         if(cType!=null) {
  227.                             cType.setParameter(HttpConstants.CONTENT_TYPE_PARAMETER_CHARSET, charsetParam);
  228.                         }
  229.                     }
  230.                    
  231.                     if(cType!=null) {
  232.                         message.setContentType(cType.toString());
  233.                     }
  234.                 }
  235.             }
  236.            
  237.             //message.saveChanges();
  238.            
  239.             return list;
  240.            
  241.         }
  242.         catch(MessageException e){
  243.             throw e;
  244.         }
  245.         catch(MessageNotSupportedException e){
  246.             throw e;
  247.         }
  248.         catch(Exception e){
  249.             throw new MessageException(e.getMessage(),e);
  250.         }
  251.     }
  252.    
  253.     public static List<MtomXomReference> packaging(OpenSPCoop2Message msgParam, List<MtomXomPackageInfo> packageInfos, boolean body) throws MessageException, MessageNotSupportedException{
  254.        
  255.         if(!MessageType.SOAP_11.equals(msgParam.getMessageType()) && !MessageType.SOAP_12.equals(msgParam.getMessageType())){
  256.             throw MessageNotSupportedException.newMessageNotSupportedException(msgParam.getMessageType());
  257.         }
  258.         OpenSPCoop2SoapMessage message = msgParam.castAsSoap();
  259.        
  260.         try{
  261.        
  262.             List<MtomXomReference> list = new ArrayList<MtomXomReference>();
  263.            
  264.             Element element = null;
  265.             Document documentSOAPPart = message.getSOAPPart();
  266.             if(body){
  267.                 element = message.getSOAPBody();
  268.             }
  269.             else{
  270.                 element = message.getSOAPPart().getEnvelope();
  271.             }
  272.             if(element==null){
  273.                 return list;
  274.             }
  275.             AbstractXPathExpressionEngine xpathEngine = new XPathExpressionEngine(msgParam.getFactory());
  276.             DynamicNamespaceContext dnc = org.openspcoop2.message.xml.MessageDynamicNamespaceContextFactory.getInstance(msgParam.getFactory()).getNamespaceContext(element);
  277.            
  278.             boolean addAttachment = false;
  279.            
  280.             if(packageInfos==null || packageInfos.size()<=0){
  281.                 return list;
  282.             }
  283.             for (MtomXomPackageInfo mtomXomPackageInfo : packageInfos) {
  284.                
  285.                 String xpathExpressionName = mtomXomPackageInfo.getName();
  286.                 String xpathExpression = mtomXomPackageInfo.getXpathExpression();
  287.                
  288.                 Object oNode = null;
  289.                 try{
  290.                     oNode = xpathEngine.getMatchPattern(element, dnc, xpathExpression, XPathReturnType.NODESET);
  291.                 }catch(XPathNotFoundException notFound){}
  292.                 if(oNode==null){
  293.                     // non esistono reference all'oggetto su cui effetture packaging
  294.                     if(mtomXomPackageInfo.isRequired()){
  295.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") not found reference");
  296.                     }
  297.                     continue;
  298.                 }
  299.                 if( !(oNode instanceof NodeList) ){
  300.                     throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") return wrong type (expected: "+
  301.                             NodeList.class.getName()+"): "+oNode.getClass().getName());
  302.                 }
  303.                 NodeList nodeList = (NodeList) oNode;
  304.                 if(nodeList.getLength()<=0){
  305.                     // non esistono reference all'oggetto su cui effetture packaging
  306.                     if(mtomXomPackageInfo.isRequired()){
  307.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") not found reference (node list is empty)");
  308.                     }
  309.                     continue;
  310.                 }
  311.                 //System.out.println("Ritornato: size: "+nodeList.getLength());
  312.                 for (int i = 0; i < nodeList.getLength(); i++) {
  313.                    
  314.                     // elementBase64
  315.                     Node elementBase64Binary = nodeList.item(i);
  316.                    
  317.                     // verifico che non sia gia un xom reference
  318.                     if(MTOMUtilities.getIfExistsXomReference(msgParam.getFactory(), (Element)elementBase64Binary)!=null){
  319.                         continue; // esiste gia' una xom reference.
  320.                     }
  321.                    
  322.                     QName qname = new QName(elementBase64Binary.getNamespaceURI(), elementBase64Binary.getLocalName());
  323.                     //System.out.println("Found Element ["+qname.toString()+"]");
  324.                     List<Node> elementBase64BinaryChilds = SoapUtils.getNotEmptyChildNodes(msgParam.getFactory(), elementBase64Binary,false);
  325.                     if(elementBase64BinaryChilds!=null && elementBase64BinaryChilds.size()>0){
  326.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  327.                                 ") with childs, mtom optimize packaging is only valid for base64Binary xsd element");
  328.                     }
  329.                     String contentTypeXMIMEAttribute = null;
  330.                     if(elementBase64Binary.hasAttributes()){
  331.                         NamedNodeMap attr = elementBase64Binary.getAttributes();
  332.                         if(attr!=null){
  333.                             for (int j = 0; j < attr.getLength(); j++) {
  334.                                 Node n = attr.item(j);
  335.                                 String localName = n.getNodeName();
  336.                                 if(localName.contains(":")){
  337.                                     localName = localName.split(":")[1];
  338.                                 }
  339.                                
  340.                                 // ignoro dichiarazioni di namespace (l'xml verra riorganizzato)
  341.                                 if(org.openspcoop2.message.constants.Costanti.XMLNS_NAMESPACE.equals(n.getNamespaceURI()) &&
  342.                                         org.openspcoop2.message.constants.Costanti.XMLNS_LOCAL_NAME.equals(localName)){
  343.                                     continue;
  344.                                 }
  345.                                
  346.                                 if(org.openspcoop2.message.soap.mtom.Costanti.XMIME_NAMESPACE.equals(n.getNamespaceURI()) &&
  347.                                         org.openspcoop2.message.soap.mtom.Costanti.XMIME_ATTRIBUTE_CONTENT_TYPE.equals(localName)){
  348.                                     contentTypeXMIMEAttribute = n.getNodeValue();
  349.                                 }else{
  350.                                     throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  351.                                             ") with attribute ({"+n.getNamespaceURI()+"}"+localName+
  352.                                             "), mtom optimize packaging is only valid for base64Binary xsd element (permit only {"+
  353.                                             org.openspcoop2.message.soap.mtom.Costanti.XMIME_NAMESPACE+"}"+org.openspcoop2.message.soap.mtom.Costanti.XMIME_ATTRIBUTE_CONTENT_TYPE+")");        
  354.                                 }
  355.                             }
  356.                         }
  357.                     }
  358.                     String base64Content = elementBase64Binary.getTextContent();
  359.                     if(base64Content==null){
  360.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  361.                                 ") without base64 value (textContent), mtom optimize packaging is only valid for base64Binary xsd element");
  362.                     }
  363.                    
  364.                    
  365.                    
  366.                     // Attachment
  367.                     String contentId = null;
  368.                     try{
  369.                         AttachmentPart ap = message.createAttachmentPart();
  370.                         String contentType = mtomXomPackageInfo.getContentType();
  371.                         if(contentType==null){
  372.                             if(contentTypeXMIMEAttribute!=null){
  373.                                 contentType = contentTypeXMIMEAttribute;
  374.                             }
  375.                             else{
  376.                                 contentType = HttpConstants.CONTENT_TYPE_APPLICATION_OCTET_STREAM;
  377.                             }
  378.                         }
  379.                         ap.setContentId(message.createContentID(org.openspcoop2.message.soap.mtom.Costanti.OPENSPCOOP2_MTOM_NAMESPACE));
  380.                         contentId = ap.getContentId();
  381.                         if(contentId.startsWith("<")){
  382.                             contentId = contentId.substring(1);
  383.                         }
  384.                         if(contentId.endsWith(">")){
  385.                             contentId = contentId.substring(0,contentId.length()-1);
  386.                         }
  387.                         ap.setBase64Content(new ByteArrayInputStream(base64Content.getBytes()), contentType);
  388.                         message.addAttachmentPart(ap);
  389.                         addAttachment = true;
  390.                     }catch(Exception e){
  391.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  392.                                 ") with base64 value (textContent). Error occurs during mtom optimize packaging (decodeBase64/createAttach): "+e.getMessage(),e);
  393.                     }
  394.                    
  395.                    
  396.                     // packaging
  397.                     elementBase64Binary.setTextContent(null);
  398.                     Element xomReference = documentSOAPPart.createElementNS(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_NAMESPACE, "xop:"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_LOCAL_NAME);
  399.                     // Non funziona in axiom
  400.                     //Attr xomReferenceHrefAttribute = documentSOAPPart.createAttribute(org.openspcoop2.message.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF);
  401.                     //xomReferenceHrefAttribute.setTextContent(org.openspcoop2.message.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE+contentId);
  402.                     //xomReference.getAttributes().setNamedItem(xomReferenceHrefAttribute);
  403.                     xomReference.setAttribute(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF, org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE+contentId);
  404.                     elementBase64Binary.appendChild(xomReference);
  405.                    
  406.                     // add reference
  407.                     MtomXomReference reference = new MtomXomReference();
  408.                     reference.setNodeName(qname);
  409.                     reference.setXomReference(xomReference);
  410.                     reference.setNode(elementBase64Binary);
  411.                     reference.setContentId(contentId);
  412.                     list.add(reference);
  413.                 }
  414.                
  415.                
  416.             }
  417.            
  418.             if(addAttachment){
  419.                 message.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE, HttpConstants.CONTENT_TYPE_APPLICATION_XOP_XML);
  420.                 if(MessageType.SOAP_11.equals(message.getMessageType())){
  421.                     message.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO, HttpConstants.CONTENT_TYPE_SOAP_1_1);
  422.                 }
  423.                 else if(MessageType.SOAP_12.equals(message.getMessageType())){
  424.                     message.addContentTypeParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO, HttpConstants.CONTENT_TYPE_SOAP_1_2);
  425.                 }
  426.             }
  427.            
  428.             //message.saveChanges();
  429.            
  430.             return list;
  431.            
  432.         }
  433.         catch(MessageException e){
  434.             throw e;
  435.         }
  436.         catch(MessageNotSupportedException e){
  437.             throw e;
  438.         }
  439.         catch(Exception e){
  440.             throw new MessageException(e.getMessage(),e);
  441.         }
  442.                
  443.     }
  444.    
  445.     public static List<MtomXomReference> verify(OpenSPCoop2Message msgParam, List<MtomXomPackageInfo> packageInfos, boolean body) throws MessageException,MessageNotSupportedException {
  446.        
  447.         if(!MessageType.SOAP_11.equals(msgParam.getMessageType()) && !MessageType.SOAP_12.equals(msgParam.getMessageType())){
  448.             throw MessageNotSupportedException.newMessageNotSupportedException(msgParam.getMessageType());
  449.         }
  450.         OpenSPCoop2SoapMessage message = msgParam.castAsSoap();
  451.        
  452.         try{
  453.            
  454.             List<MtomXomReference> list = new ArrayList<MtomXomReference>();
  455.            
  456.             Element element = null;
  457.             if(body){
  458.                 element = message.getSOAPBody();
  459.             }
  460.             else{
  461.                 element = message.getSOAPPart().getEnvelope();
  462.             }
  463.             if(element==null){
  464.                 return list;
  465.             }
  466.             AbstractXPathExpressionEngine xpathEngine = new XPathExpressionEngine(msgParam.getFactory());
  467.             DynamicNamespaceContext dnc = org.openspcoop2.message.xml.MessageDynamicNamespaceContextFactory.getInstance(msgParam.getFactory()).getNamespaceContext(element);
  468.            
  469.             if(packageInfos==null || packageInfos.size()<=0){
  470.                 return list;
  471.             }
  472.             for (MtomXomPackageInfo mtomXomPackageInfo : packageInfos) {
  473.                
  474.                 String xpathExpressionName = mtomXomPackageInfo.getName();
  475.                 String xpathExpression = mtomXomPackageInfo.getXpathExpression();
  476.                
  477.                 Object oNode = null;
  478.                 try{
  479.                     oNode = xpathEngine.getMatchPattern(element, dnc, xpathExpression, XPathReturnType.NODESET);
  480.                 }catch(XPathNotFoundException notFound){}
  481.                 if(oNode==null){
  482.                     // non esistono reference all'oggetto su cui effetture packaging
  483.                     if(mtomXomPackageInfo.isRequired()){
  484.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") not found reference");
  485.                     }
  486.                     continue;
  487.                 }
  488.                 if( !(oNode instanceof NodeList) ){
  489.                     throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") return wrong type (expected: "+
  490.                             NodeList.class.getName()+"): "+oNode.getClass().getName());
  491.                 }
  492.                 NodeList nodeList = (NodeList) oNode;
  493.                 if(nodeList.getLength()<=0){
  494.                     // non esistono reference all'oggetto su cui effetture packaging
  495.                     if(mtomXomPackageInfo.isRequired()){
  496.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") not found reference (node list is empty)");
  497.                     }
  498.                     continue;
  499.                 }
  500.                 //System.out.println("Ritornato: size: "+nodeList.getLength());
  501.                 for (int i = 0; i < nodeList.getLength(); i++) {
  502.                    
  503.                     // elementBase64
  504.                     Node elementBase64Binary = nodeList.item(i);
  505.                     QName qname = new QName(elementBase64Binary.getNamespaceURI(), elementBase64Binary.getLocalName());
  506.                     //System.out.println("Found Element ["+qname.toString()+"]");
  507.                     if(elementBase64Binary.hasAttributes()){
  508.                         NamedNodeMap attr = elementBase64Binary.getAttributes();
  509.                         if(attr!=null){
  510.                             for (int j = 0; j < attr.getLength(); j++) {
  511.                                 Node n = attr.item(j);
  512.                                 String localName = n.getNodeName();
  513.                                 if(localName.contains(":")){
  514.                                     localName = localName.split(":")[1];
  515.                                 }
  516.                                
  517.                                 // ignoro dichiarazioni di namespace (l'xml verra riorganizzato)
  518.                                 if(org.openspcoop2.message.constants.Costanti.XMLNS_NAMESPACE.equals(n.getNamespaceURI()) &&
  519.                                         org.openspcoop2.message.constants.Costanti.XMLNS_LOCAL_NAME.equals(localName)){
  520.                                     continue;
  521.                                 }
  522.                                
  523.                                 // ignoro dichiarazione di content type
  524.                                 if(org.openspcoop2.message.soap.mtom.Costanti.XMIME_NAMESPACE.equals(n.getNamespaceURI()) &&
  525.                                         org.openspcoop2.message.soap.mtom.Costanti.XMIME_ATTRIBUTE_CONTENT_TYPE.equals(localName)){
  526.                                     continue;
  527.                                 }
  528.                                
  529.                                 throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  530.                                         ") with attribute ({"+n.getNamespaceURI()+"}"+localName+
  531.                                             "), mtom optimize packaging structure invalid");
  532.                             }
  533.                         }
  534.                            
  535.                     }
  536.                     List<Node> nodeListBase64 = SoapUtils.getNotEmptyChildNodes(msgParam.getFactory(), elementBase64Binary,false);
  537.                     if(nodeListBase64==null || nodeListBase64.size()<=0){
  538.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  539.                                 ") without childs, mtom optimize packaging require xop:"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_LOCAL_NAME+" element");
  540.                     }
  541.                     if(nodeListBase64.size()>1){
  542.                         throw new MessageException("XpathEngine (expr("+xpathExpressionName+"):"+xpathExpression+") found element ("+qname+
  543.                                 ") with more than one child, mtom optimize packaging structure invalid");
  544.                     }
  545.                    
  546.                     // xomReference
  547.                     Node xomReference = nodeListBase64.get(0);
  548.                     if(xomReference.getAttributes()==null || xomReference.getAttributes().getLength()<=0){
  549.                         throw new MessageException("Found XOM Reference without attributes ('"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' attribute required)");
  550.                     }
  551.                     Node xomHref = xomReference.getAttributes().getNamedItem(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF);
  552.                     if(xomHref == null){
  553.                         throw new MessageException("Found XOM Reference without attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"'");
  554.                     }
  555.                     String contentId = xomHref.getNodeValue();
  556.                     if(contentId == null){
  557.                         throw new MessageException("Found XOM Reference with attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' without value?");
  558.                     }
  559.                     if(contentId.startsWith(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE)){
  560.                         contentId = contentId.substring(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE.length());
  561.                     }
  562.                     MimeHeaders mhs = new MimeHeaders();
  563.                     mhs.addHeader(HttpConstants.CONTENT_ID, contentId);
  564.                     Iterator<?> itAttachments = message.getAttachments(mhs);
  565.                     if(itAttachments == null || itAttachments.hasNext()==false){
  566.                         throw new MessageException("Found XOM Reference with attribute ["+
  567.                                 org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but the message hasn't attachments");
  568.                     }
  569.                     AttachmentPart ap = null;
  570.                     while (itAttachments.hasNext()) {
  571.                         if(ap!=null){
  572.                             throw new MessageException("Found XOM Reference with attribute ["+
  573.                                     org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but exists more than one attachment with same id");
  574.                         }
  575.                         ap = (AttachmentPart) itAttachments.next();
  576.                     }
  577.                     if(ap==null){
  578.                         throw new MessageException("Found XOM Reference with attribute ["+
  579.                                 org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"] but not exists attachment with same id");
  580.                     }  
  581.                     String contentType = mtomXomPackageInfo.getContentType();
  582.                     if(contentType==null){
  583.                         contentType = HttpConstants.CONTENT_TYPE_APPLICATION_OCTET_STREAM;
  584.                     }
  585.                     if(ap.getContentType()==null){
  586.                         throw new MessageException("Found XOM Reference with attribute ["+
  587.                                 org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"]. The attachment hasn't content-type");
  588.                     }
  589.                     else{
  590.                         String apCT = ap.getContentType();
  591.                         String base = ContentTypeUtilities.readBaseTypeFromContentType(apCT);
  592.                         if(contentType.equals(base)==false){
  593.                             throw new MessageException("Found XOM Reference with attribute ["+
  594.                                     org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+contentId+"]. The attachment has wrong content-type (expected:"+contentType+"): "+ap.getContentType());
  595.                         }
  596.                     }
  597.                                        
  598.                     // add reference
  599.                     MtomXomReference reference = new MtomXomReference();
  600.                     reference.setNodeName(qname);
  601.                     reference.setXomReference(xomReference);
  602.                     reference.setNode(elementBase64Binary);
  603.                     reference.setContentId(contentId);
  604.                     list.add(reference);
  605.                 }
  606.                
  607.                
  608.             }
  609.            
  610.             return list;
  611.            
  612.         }
  613.         catch(MessageException e){
  614.             throw e;
  615.         }
  616.         catch(MessageNotSupportedException e){
  617.             throw e;
  618.         }
  619.         catch(Exception e){
  620.             throw new MessageException(e.getMessage(),e);
  621.         }
  622.        
  623.     }
  624.    
  625.     public static void restoreAfterFastUnpackaging(OpenSPCoop2Message msgParam, List<MtomXomReference> references, boolean body) throws MessageException,MessageNotSupportedException {
  626.    
  627.         if(!MessageType.SOAP_11.equals(msgParam.getMessageType()) && !MessageType.SOAP_12.equals(msgParam.getMessageType())){
  628.             throw MessageNotSupportedException.newMessageNotSupportedException(msgParam.getMessageType());
  629.         }
  630.         OpenSPCoop2SoapMessage message = msgParam.castAsSoap();
  631.        
  632.         try{
  633.        
  634.             Element element = null;
  635.             if(body){
  636.                 element = message.getSOAPBody();
  637.             }
  638.             else{
  639.                 element = message.getSOAPPart().getEnvelope();
  640.             }
  641.             if(element==null){
  642.                 return;
  643.             }
  644.            
  645.             if(references==null || references.size()<=0){
  646.                 return;
  647.             }
  648.            
  649.             for (MtomXomReference mtomXomReference : references) {
  650.                
  651.                 if(mtomXomReference.getNode()==null){
  652.                     throw new MessageException("XomReference ["+mtomXomReference.getNodeName()+"] with undefined node");
  653.                 }
  654.                 if(mtomXomReference.getXomReference()==null){
  655.                     throw new MessageException("XomReference ["+mtomXomReference.getNodeName()+"] with undefined xomRerefence");
  656.                 }
  657.                 mtomXomReference.getNode().setTextContent(null);
  658.                 mtomXomReference.getNode().appendChild(mtomXomReference.getXomReference());
  659.                
  660.             }
  661.            
  662.             //message.saveChanges();
  663.         }
  664.         catch(MessageException e){
  665.             throw e;
  666.         }
  667.         catch(MessageNotSupportedException e){
  668.             throw e;
  669.         }
  670.         catch(Exception e){
  671.             throw new MessageException(e.getMessage(),e);
  672.         }
  673.        
  674.     }
  675.    
  676.     public static Element getIfExistsXomReference(OpenSPCoop2MessageFactory messageFactory, Element element){
  677.        
  678.         try{
  679.             Node n = SoapUtils.getFirstNotEmptyChildNode(messageFactory, element,false);
  680.             if(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_LOCAL_NAME.equals(n.getLocalName()) &&
  681.                     org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_NAMESPACE.equals(n.getNamespaceURI())){
  682.                 return (Element)n;
  683.             }
  684. //          
  685. //          La ricerca con XPath ritornava anche gli elementi del padre.
  686. //          AbstractXPathExpressionEngine xpathEngine = new XPathExpressionEngine();
  687. //          DynamicNamespaceContext dnc = org.openspcoop2.message.DynamicNamespaceContextFactory.getInstance().getNamespaceContext(element);
  688. //          Object oNode = xpathEngine.getMatchPattern(element, dnc, org.openspcoop2.message.mtom.Costanti.MTOM_XOP_REFERENCES, XPathReturnType.NODE);
  689. //          return (Element) oNode;
  690.            
  691.             return null;
  692.            
  693.         }catch(Exception e){
  694.             return null;
  695.         }
  696.     }
  697.    
  698.     public static String getCidXomReference(Element element) throws MessageException {
  699.         if(element.getAttributes()==null || element.getAttributes().getLength()<=0){
  700.             throw new MessageException("Found XOM Reference without attributes ('"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' attribute required)");
  701.         }
  702.         Node xomHref = element.getAttributes().getNamedItem(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF);
  703.         if(xomHref == null){
  704.             throw new MessageException("Found XOM Reference without attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"'");
  705.         }
  706.         String contentId = xomHref.getNodeValue();
  707.         if(contentId == null){
  708.             throw new MessageException("Found XOM Reference with attribute '"+org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"' without value?");
  709.         }
  710.         if(contentId.startsWith(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE)){
  711.             contentId = contentId.substring(org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF_CID_PREFIX_VALUE.length());
  712.         }
  713.         return contentId;
  714.     }
  715.    
  716.     public static AttachmentPart getAttachmentPart(OpenSPCoop2Message msgParam, String cidReference) throws MessageException,MessageNotSupportedException {
  717.        
  718.         if(!MessageType.SOAP_11.equals(msgParam.getMessageType()) && !MessageType.SOAP_12.equals(msgParam.getMessageType())){
  719.             throw MessageNotSupportedException.newMessageNotSupportedException(msgParam.getMessageType());
  720.         }
  721.         OpenSPCoop2SoapMessage message = msgParam.castAsSoap();
  722.        
  723.         MimeHeaders mhs = new MimeHeaders();
  724.         mhs.addHeader(HttpConstants.CONTENT_ID, cidReference);
  725.         Iterator<?> itAttachments = message.getAttachments(mhs);
  726.         if(itAttachments == null || itAttachments.hasNext()==false){
  727.             throw new MessageException("Found XOM Reference with attribute ["+
  728.                     org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+cidReference+"] but the message hasn't attachments");
  729.         }
  730.         AttachmentPart ap = null;
  731.         while (itAttachments.hasNext()) {
  732.             if(ap!=null){
  733.                 throw new MessageException("Found XOM Reference with attribute ["+
  734.                         org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+cidReference+"] but exists more than one attachment with same id");
  735.             }
  736.             ap = (AttachmentPart) itAttachments.next();
  737.         }
  738.         if(ap==null){
  739.             throw new MessageException("Found XOM Reference with attribute ["+
  740.                     org.openspcoop2.message.soap.mtom.Costanti.XOP_INCLUDE_ATTRIBUTE_HREF+"]=["+cidReference+"] but not exists attachment with same id");
  741.         }
  742.         return ap;
  743.     }
  744. }