You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by ge...@apache.org on 2002/09/04 08:33:10 UTC

cvs commit: xml-security/src/org/apache/xml/security/signature Reference.java XMLSignatureInput.java

geuerp      2002/09/03 23:33:10

  Modified:    src/org/apache/xml/security/signature Reference.java
                        XMLSignatureInput.java
  Log:
  XMLSignatureInput and Reference now support a debuggingFunctionality:
  
  XMLSignatureInput offers the methods
  
    String getHTMLRepresentation
    String getHTMLRepresentation(Set inclusiveNamespaces)
  
  which do work if the internal representation is a node set. They return an HTML representation of the node set.
  
  When a Reference contains Transforms, the new getNodesetBeforeFirstCanonicalization returns the last existing node set. This allows to debug canonicalization algorithms more easily and allows users to check which node set has been canonicalized.
  
  Revision  Changes    Path
  1.26      +178 -40   xml-security/src/org/apache/xml/security/signature/Reference.java
  
  Index: Reference.java
  ===================================================================
  RCS file: /home/cvs/xml-security/src/org/apache/xml/security/signature/Reference.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Reference.java	2 Sep 2002 14:34:46 -0000	1.25
  +++ Reference.java	4 Sep 2002 06:33:10 -0000	1.26
  @@ -1,3 +1,4 @@
  +
   /*
    * The Apache Software License, Version 1.1
    *
  @@ -59,6 +60,7 @@
   package org.apache.xml.security.signature;
   
   
  +
   import java.io.*;
   import java.math.BigInteger;
   import java.util.*;
  @@ -66,12 +68,10 @@
   import javax.xml.parsers.DocumentBuilderFactory;
   import javax.xml.parsers.ParserConfigurationException;
   import javax.xml.transform.TransformerException;
  -
   import org.w3c.dom.*;
   import org.w3c.dom.traversal.NodeIterator;
   import org.xml.sax.InputSource;
   import org.xml.sax.SAXException;
  -
   import org.apache.xml.serialize.OutputFormat;
   import org.apache.xml.serialize.Serializer;
   import org.apache.xml.serialize.SerializerFactory;
  @@ -82,9 +82,9 @@
   import org.apache.xpath.XPath;
   import org.apache.xpath.XPathAPI;
   import org.apache.xpath.XPathContext;
  -
   import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
   import org.apache.xml.security.c14n.*;
  +import org.apache.xml.security.transforms.params.InclusiveNamespaces;
   import org.apache.xml.security.exceptions.*;
   import org.apache.xml.security.signature.*;
   import org.apache.xml.security.transforms.*;
  @@ -93,7 +93,6 @@
   import org.apache.xml.security.utils.resolver.*;
   
   
  -
   /**
    * Handles <code>&lt;ds:Reference&gt;</code> elements.
    *
  @@ -142,6 +141,7 @@
    */
   public class Reference extends SignatureElementProxy {
   
  +   /** Field CacheSignedNodes */
      public static boolean CacheSignedNodes = false;
   
      /** {@link org.apache.log4j} logging facility */
  @@ -173,9 +173,8 @@
       * $todo$ should we throw XMLSignatureException if MessageDigestAlgoURI is wrong?
       * @throws XMLSignatureException
       */
  -   protected Reference(
  -           Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms, String messageDigestAlgorithm)
  -              throws XMLSignatureException {
  +   protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms, String messageDigestAlgorithm)
  +           throws XMLSignatureException {
   
         super(doc);
   
  @@ -224,9 +223,8 @@
       * @param messageDigestAlgorithm  {@link MessageDigestAlgorithm Digest algorithm} which is applied to the data
       * @throws XMLSignatureException
       */
  -   protected Reference(
  -           Document doc, String BaseURI, String ReferenceURI, Manifest manifest, String messageDigestAlgorithm)
  -              throws XMLSignatureException {
  +   protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest, String messageDigestAlgorithm)
  +           throws XMLSignatureException {
         this(doc, BaseURI, ReferenceURI, manifest, (Transforms) null,
              messageDigestAlgorithm);
      }
  @@ -241,9 +239,8 @@
       * @param transforms {@link Transforms} applied to data
       * @throws XMLSignatureException
       */
  -   protected Reference(
  -           Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms)
  -              throws XMLSignatureException {
  +   protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest, Transforms transforms)
  +           throws XMLSignatureException {
         this(doc, BaseURI, ReferenceURI, manifest, transforms,
              Constants.ALGO_ID_DIGEST_SHA1);
      }
  @@ -257,9 +254,8 @@
       * @param manifest
       * @throws XMLSignatureException
       */
  -   protected Reference(
  -           Document doc, String BaseURI, String ReferenceURI, Manifest manifest)
  -              throws XMLSignatureException {
  +   protected Reference(Document doc, String BaseURI, String ReferenceURI, Manifest manifest)
  +           throws XMLSignatureException {
         this(doc, BaseURI, ReferenceURI, manifest, (Transforms) null,
              Constants.ALGO_ID_DIGEST_SHA1);
      }
  @@ -292,14 +288,14 @@
              throws XMLSignatureException {
   
         Element digestMethodElem = this.getChildElementLocalName(0,
  -                                    Constants.SignatureSpecNS,
  -                                    Constants._TAG_DIGESTMETHOD);
  +         Constants.SignatureSpecNS, Constants._TAG_DIGESTMETHOD);
   
         if (digestMethodElem == null) {
            return null;
         }
   
  -      String uri = digestMethodElem.getAttributeNS(null, Constants._ATT_ALGORITHM);
  +      String uri = digestMethodElem.getAttributeNS(null,
  +         Constants._ATT_ALGORITHM);
   
         return MessageDigestAlgorithm.getInstance(this._doc, uri);
      }
  @@ -312,7 +308,8 @@
      public void setURI(String URI) {
   
         if ((this._state == MODE_SIGN) && (URI != null)) {
  -         this._constructionElement.setAttributeNS(null, Constants._ATT_URI, URI);
  +         this._constructionElement.setAttributeNS(null, Constants._ATT_URI,
  +                                                  URI);
         }
      }
   
  @@ -355,7 +352,8 @@
      public void setType(String Type) {
   
         if ((this._state == MODE_SIGN) && (Type != null)) {
  -         this._constructionElement.setAttributeNS(null, Constants._ATT_TYPE, Type);
  +         this._constructionElement.setAttributeNS(null, Constants._ATT_TYPE,
  +                                                  Type);
         }
      }
   
  @@ -365,7 +363,8 @@
       * @return the <code>type</code> attribute of the Reference
       */
      public String getType() {
  -      return this._constructionElement.getAttributeNS(null, Constants._ATT_TYPE);
  +      return this._constructionElement.getAttributeNS(null,
  +              Constants._ATT_TYPE);
      }
   
      /**
  @@ -415,8 +414,7 @@
   
         if (this._state == MODE_SIGN) {
            Element digestValueElement = this.getChildElementLocalName(0,
  -                                         Constants.SignatureSpecNS,
  -                                         Constants._TAG_DIGESTVALUE);
  +            Constants.SignatureSpecNS, Constants._TAG_DIGESTVALUE);
            NodeList children = digestValueElement.getChildNodes();
   
            for (int i = 0; i < children.getLength(); i++) {
  @@ -449,10 +447,12 @@
      /**
       * Returns the XMLSignatureInput which is created by de-referencing the URI attribute.
       */
  -   public XMLSignatureInput getContentsBeforeTransformation () throws ReferenceNotInitializedException {
  +   public XMLSignatureInput getContentsBeforeTransformation()
  +           throws ReferenceNotInitializedException {
  +
         try {
  -         Attr URIAttr =
  -            this._constructionElement.getAttributeNodeNS(null, Constants._ATT_URI);
  +         Attr URIAttr = this._constructionElement.getAttributeNodeNS(null,
  +            Constants._ATT_URI);
            String URI;
   
            if (URIAttr == null) {
  @@ -462,8 +462,7 @@
            }
   
            ResourceResolver resolver = ResourceResolver.getInstance(URIAttr,
  -                                        this._baseURI,
  -                                        this._manifest._perManifestResolvers);
  +            this._baseURI, this._manifest._perManifestResolvers);
   
            if (resolver == null) {
               Object exArgs[] = { URI };
  @@ -477,6 +476,7 @@
            XMLSignatureInput input = resolver.resolve(URIAttr, this._baseURI);
   
            this._transformsInput = new XMLSignatureInput(input.getBytes());
  +
            this._transformsInput.setSourceURI(input.getSourceURI());
   
            return input;
  @@ -499,19 +499,20 @@
         return this._transformsInput;
      }
   
  -   private XMLSignatureInput getContentsAfterTransformation (XMLSignatureInput input) throws XMLSignatureException {
  +   private XMLSignatureInput getContentsAfterTransformation(XMLSignatureInput input)
  +           throws XMLSignatureException {
  +
         try {
            Transforms transforms = this.getTransforms();
  -
            XMLSignatureInput output = null;
  +
            if (transforms != null) {
               output = transforms.performTransforms(input);
  -
               this._transformsOutput = new XMLSignatureInput(output.getBytes());
  +
               this._transformsOutput.setSourceURI(output.getSourceURI());
            } else {
               output = input;
  -
               this._transformsOutput = this._transformsInput;
            }
   
  @@ -534,13 +535,150 @@
      /**
       * Returns the XMLSignatureInput which is the result of the Transforms.
       */
  -   public XMLSignatureInput getContentsAfterTransformation () throws XMLSignatureException {
  +   public XMLSignatureInput getContentsAfterTransformation()
  +           throws XMLSignatureException {
  +
         XMLSignatureInput input = this.getContentsBeforeTransformation();
   
         return this.getContentsAfterTransformation(input);
      }
   
      /**
  +    * This method returns the XMLSignatureInput which represents the node set before
  +    * some kind of canonicalization is applied for the first time.
  +    *
  +    * @throws XMLSignatureException
  +    */
  +   public XMLSignatureInput getNodesetBeforeFirstCanonicalization()
  +           throws XMLSignatureException {
  +
  +      try {
  +         XMLSignatureInput input = this.getContentsBeforeTransformation();
  +         XMLSignatureInput output = input;
  +         Transforms transforms = this.getTransforms();
  +         Transform c14nTransform = null;
  +
  +         if (transforms != null) {
  +            doTransforms: for (int i = 0; i < transforms.getLength(); i++) {
  +               Transform t = transforms.item(i);
  +               String URI = t.getURI();
  +
  +               if (URI.equals(Transforms
  +                       .TRANSFORM_C14N_EXCL_OMIT_COMMENTS) || URI
  +                          .equals(Transforms
  +                             .TRANSFORM_C14N_EXCL_WITH_COMMENTS) || URI
  +                                .equals(Transforms
  +                                   .TRANSFORM_C14N_OMIT_COMMENTS) || URI
  +                                      .equals(Transforms
  +                                         .TRANSFORM_C14N_WITH_COMMENTS)) {
  +                  c14nTransform = t;
  +
  +                  break doTransforms;
  +               }
  +
  +               output = t.performTransform(output);
  +            }
  +
  +            output.setSourceURI(input.getSourceURI());
  +         }
  +
  +         if (c14nTransform != null) {
  +            String URI = c14nTransform.getURI();
  +
  +            if (URI.equals(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS)
  +                    || URI.equals(
  +                       Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS)) {
  +               if (c14nTransform
  +                       .length(InclusiveNamespaces
  +                          .ExclusiveCanonicalizationNamespace, InclusiveNamespaces
  +                          ._TAG_EC_INCLUSIVENAMESPACES) == 1) {
  +                  Element inE = c14nTransform.getChildElementLocalName(0,
  +                     InclusiveNamespaces.ExclusiveCanonicalizationNamespace,
  +                     InclusiveNamespaces._TAG_EC_INCLUSIVENAMESPACES);
  +                  InclusiveNamespaces in = new InclusiveNamespaces(inE,
  +                     this.getBaseURI());
  +                  String ins = in.getInclusiveNamespaces();
  +               }
  +            }
  +         }
  +
  +         return output;
  +      } catch (IOException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (ResourceResolverException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (CanonicalizationException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (InvalidCanonicalizerException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (TransformationException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (XMLSecurityException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      }
  +   }
  +
  +   /**
  +    * Method getHTMLRepresentation
  +    *
  +    * @throws XMLSignatureException
  +    */
  +   public String getHTMLRepresentation() throws XMLSignatureException {
  +
  +      try {
  +         XMLSignatureInput nodes = this.getNodesetBeforeFirstCanonicalization();
  +         Set inclusiveNamespaces = new HashSet();
  +
  +         {
  +            Transforms transforms = this.getTransforms();
  +            Transform c14nTransform = null;
  +
  +            if (transforms != null) {
  +               doTransforms: for (int i = 0; i < transforms.getLength(); i++) {
  +                  Transform t = transforms.item(i);
  +                  String URI = t.getURI();
  +
  +                  if (URI.equals(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS)
  +                          || URI.equals(
  +                             Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS)) {
  +                     c14nTransform = t;
  +
  +                     break doTransforms;
  +                  }
  +               }
  +            }
  +
  +            if (c14nTransform != null) {
  +               String URI = c14nTransform.getURI();
  +
  +               if (c14nTransform
  +                       .length(InclusiveNamespaces
  +                          .ExclusiveCanonicalizationNamespace, InclusiveNamespaces
  +                          ._TAG_EC_INCLUSIVENAMESPACES) == 1) {
  +
  +                  // there is one InclusiveNamespaces element
  +                  InclusiveNamespaces in = new InclusiveNamespaces(c14nTransform
  +                     .getChildElementLocalName(0, InclusiveNamespaces
  +                        .ExclusiveCanonicalizationNamespace, InclusiveNamespaces
  +                        ._TAG_EC_INCLUSIVENAMESPACES), this.getBaseURI());
  +
  +                  inclusiveNamespaces = InclusiveNamespaces.prefixStr2Set(
  +                     in.getInclusiveNamespaces());
  +               }
  +            }
  +         }
  +
  +         return nodes.getHTMLRepresentation(inclusiveNamespaces);
  +      } catch (TransformationException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (InvalidTransformException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      } catch (XMLSecurityException ex) {
  +         throw new XMLSignatureException("empty", ex);
  +      }
  +   }
  +
  +   /**
       * This method only works works after a call to verify.
       *
       */
  @@ -555,10 +693,10 @@
       * @throws XMLSignatureException
       * @see Manifest#verifyReferences
       */
  -   protected void dereferenceURIandPerformTransforms() throws XMLSignatureException {
  +   protected void dereferenceURIandPerformTransforms()
  +           throws XMLSignatureException {
   
         try {
  -
            XMLSignatureInput input = this.getContentsBeforeTransformation();
            XMLSignatureInput output = this.getContentsAfterTransformation(input);
   
  @@ -569,9 +707,11 @@
             */
            if (!Reference.CacheSignedNodes) {
               this._transformsInput = new XMLSignatureInput(input.getBytes());
  +
               this._transformsInput.setSourceURI(input.getSourceURI());
   
               this._transformsOutput = new XMLSignatureInput(output.getBytes());
  +
               this._transformsOutput.setSourceURI(output.getSourceURI());
            }
         } catch (IOException ex) {
  @@ -599,8 +739,7 @@
                     TransformationException, XMLSecurityException {
   
         Element transformsElement = this.getChildElementLocalName(0,
  -                                     Constants.SignatureSpecNS,
  -                                     Constants._TAG_TRANSFORMS);
  +         Constants.SignatureSpecNS, Constants._TAG_TRANSFORMS);
   
         if (transformsElement != null) {
            Transforms transforms = new Transforms(transformsElement,
  @@ -680,8 +819,7 @@
              throws ReferenceNotInitializedException, XMLSecurityException {
   
         Element digestValueElem = this.getChildElementLocalName(0,
  -                                   Constants.SignatureSpecNS,
  -                                   Constants._TAG_DIGESTVALUE);
  +         Constants.SignatureSpecNS, Constants._TAG_DIGESTVALUE);
         byte[] elemDig = Base64.decode(digestValueElem);
         byte[] calcDig = this.calculateDigest();
         boolean equal = MessageDigestAlgorithm.isEqual(elemDig, calcDig);
  
  
  
  1.18      +597 -31   xml-security/src/org/apache/xml/security/signature/XMLSignatureInput.java
  
  Index: XMLSignatureInput.java
  ===================================================================
  RCS file: /home/cvs/xml-security/src/org/apache/xml/security/signature/XMLSignatureInput.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- XMLSignatureInput.java	29 Aug 2002 16:05:47 -0000	1.17
  +++ XMLSignatureInput.java	4 Sep 2002 06:33:10 -0000	1.18
  @@ -1,3 +1,4 @@
  +
   /*
    * The Apache Software License, Version 1.1
    *
  @@ -60,33 +61,20 @@
   
   
   
  -import java.io.File;
  -import java.io.InputStream;
  -import java.io.FileInputStream;
  -import java.io.Reader;
  -import java.io.StringReader;
  -import java.io.FileNotFoundException;
  -import java.io.IOException;
  -import java.io.ByteArrayOutputStream;
  -import java.io.ByteArrayInputStream;
  -import java.io.UnsupportedEncodingException;
  +import java.io.*;
   import java.util.*;
  -import org.w3c.dom.*;
  -import org.xml.sax.InputSource;
   import javax.xml.parsers.*;
  -import org.apache.xml.security.utils.Constants;
  -import org.apache.xml.security.exceptions.XMLSecurityException;
  -import org.apache.xml.security.c14n.*;
  -import org.apache.xml.security.c14n.implementations.*;
  -import org.apache.xml.security.utils.XMLUtils;
  -import org.apache.xml.security.utils.JavaUtils;
  -import org.apache.xml.security.utils.HelperNodeList;
   import javax.xml.parsers.ParserConfigurationException;
   import javax.xml.transform.TransformerException;
  -import java.io.IOException;
  -import org.xml.sax.SAXException;
  +import org.apache.xml.security.c14n.*;
  +import org.apache.xml.security.c14n.implementations.*;
  +import org.apache.xml.security.exceptions.XMLSecurityException;
  +import org.apache.xml.security.utils.*;
   import org.apache.xpath.CachedXPathAPI;
   import org.apache.xpath.XPathContext;
  +import org.w3c.dom.*;
  +import org.xml.sax.InputSource;
  +import org.xml.sax.SAXException;
   
   
   /**
  @@ -183,10 +171,11 @@
   
         // get the Document and make all namespace nodes visible in DOM space
         Document doc = XMLUtils.getOwnerDocument(rootNode);
  +
         XMLUtils.circumventBug2650(doc);
   
         NodeList result = this._cxpathAPI.selectNodeList(rootNode,
  -                           Canonicalizer.XPATH_C14N_WITH_COMMENTS_SINGLE_NODE);
  +         Canonicalizer.XPATH_C14N_WITH_COMMENTS_SINGLE_NODE);
   
         this._inputNodeSet = XMLUtils.convertNodelistToSet(result);
      }
  @@ -247,19 +236,16 @@
            DocumentBuilder db = dfactory.newDocumentBuilder();
   
            try {
  -            db.setErrorHandler(new org.apache.xml.security.utils
  -               .IgnoreAllErrorHandler());
  +            db.setErrorHandler(
  +               new org.apache.xml.security.utils.IgnoreAllErrorHandler());
   
               Document doc = db.parse(this.getOctetStream());
   
               XMLUtils.circumventBug2650(doc);
   
               // select all nodes, also the comments.
  -            NodeList nodeList =
  -               this._cxpathAPI
  -                  .selectNodeList(doc,
  -                                  Canonicalizer
  -                                     .XPATH_C14N_WITH_COMMENTS_SINGLE_NODE);
  +            NodeList nodeList = this._cxpathAPI.selectNodeList(doc,
  +               Canonicalizer.XPATH_C14N_WITH_COMMENTS_SINGLE_NODE);
   
               return XMLUtils.convertNodelistToSet(nodeList);
            } catch (TransformerException ex) {
  @@ -275,11 +261,11 @@
   
               byte result[] = baos.toByteArray();
               Document document = db.parse(new ByteArrayInputStream(result));
  +
               XMLUtils.circumventBug2650(document);
   
               try {
  -               NodeList nodeList = this._cxpathAPI.selectNodeList(
  -                  document,
  +               NodeList nodeList = this._cxpathAPI.selectNodeList(document,
                     "(//. | //@* | //namespace::*)[not(self::node()=/) and not(self::node=/container)]");
   
                  return XMLUtils.convertNodelistToSet(nodeList);
  @@ -488,6 +474,586 @@
                      + " octets/" + this.getSourceURI();
            } catch (Exception ex) {
               return "XMLSignatureInput/OctetStream//" + this.getSourceURI();
  +         }
  +      }
  +   }
  +
  +   /**
  +    * Method getHTMLRepresentation
  +    *
  +    * @throws XMLSignatureException
  +    */
  +   public String getHTMLRepresentation() throws XMLSignatureException {
  +
  +      XMLSignatureInputDebugger db = new XMLSignatureInputDebugger(this);
  +
  +      return db.getHTMLRepresentation();
  +   }
  +
  +   /**
  +    * Method getHTMLRepresentation
  +    *
  +    * @param inclusiveNamespaces
  +    * @throws XMLSignatureException
  +    */
  +   public String getHTMLRepresentation(Set inclusiveNamespaces)
  +           throws XMLSignatureException {
  +
  +      XMLSignatureInputDebugger db = new XMLSignatureInputDebugger(this,
  +         inclusiveNamespaces);
  +
  +      return db.getHTMLRepresentation();
  +   }
  +
  +   /**
  +    * Class XMLSignatureInputDebugger
  +    *
  +    * @author $Author$
  +    * @version $Revision$
  +    */
  +   public class XMLSignatureInputDebugger {
  +
  +      /** Field _xmlSignatureInput */
  +      private Set _xpathNodeSet;
  +      private Set _inclusiveNamespaces;
  +
  +      /** Field _doc */
  +      private Document _doc = null;
  +
  +      /** Field _documentElement */
  +      private Element _documentElement = null;
  +
  +      /** Field _writer */
  +      private Writer _writer = null;
  +
  +      /** Field HTMLPrefix */
  +      public static final String HTMLPrefix =    /* "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" + */
  +         "<html>\n<head>\n<style type=\"text/css\">\n<!--\n"
  +         + ".INCLUDE { color: #000000; background-color: #FFFFFF; } "
  +         + ".INCLUSIVENAMESPACE { color: #FF0000; background-color: #FFFFFF; font-weight: bold; } "
  +         + "\n-->\n</style>\n</head>\n<body>\n<pre>";
  +
  +      /** Field HTMLSuffix */
  +      public static final String HTMLSuffix = "</pre></body></html>";
  +
  +      /** Field ExcludePrefix */
  +      public static final String HTMLExcludePrefix = "<span class=\"INCLUDE\">";
  +
  +      /** Field ExcludeSuffix */
  +      public static final String HTMLExcludeSuffix = "</span>";
  +
  +      /** Field HTMLInclusiveNamespacePrefix */
  +      public static final String HTMLInclusiveNamespacePrefix =
  +         "<b>";
  +
  +      /** Field HTMLInclusiveNamespaceSuffix */
  +      public static final String HTMLInclusiveNamespaceSuffix = "</b>";
  +      //J-
  +      private static final int NODE_BEFORE_DOCUMENT_ELEMENT = -1;
  +      private static final int NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT = 0;
  +      private static final int NODE_AFTER_DOCUMENT_ELEMENT = 1;
  +      //J+
  +      private XMLSignatureInputDebugger() {
  +         ;
  +      }
  +
  +      /**
  +       * Constructor XMLSignatureInputDebugger
  +       *
  +       * @param xmlSignatureInput
  +       */
  +      public XMLSignatureInputDebugger(XMLSignatureInput xmlSignatureInput)
  +              throws XMLSignatureException {
  +
  +         if (!xmlSignatureInput.isNodeSet()) {
  +            this._xpathNodeSet = null;
  +         } else {
  +            this._xpathNodeSet = xmlSignatureInput._inputNodeSet;
  +         }
  +      }
  +
  +      /**
  +       * Constructor XMLSignatureInputDebugger
  +       *
  +       * @param xmlSignatureInput
  +       * @param inclusiveNamespace
  +       * @throws XMLSignatureException
  +       */
  +      public XMLSignatureInputDebugger(XMLSignatureInput xmlSignatureInput, Set inclusiveNamespace)
  +              throws XMLSignatureException {
  +
  +         this(xmlSignatureInput);
  +
  +         this._inclusiveNamespaces = inclusiveNamespace;
  +      }
  +
  +      /**
  +       * Method getHTMLRepresentation
  +       *
  +       */
  +      public String getHTMLRepresentation() throws XMLSignatureException {
  +
  +         if ((this._xpathNodeSet == null) || (this._xpathNodeSet.size() == 0)) {
  +            return HTMLPrefix + "<blink>no node set, sorry</blink>"
  +                   + HTMLSuffix;
  +         }
  +
  +         {
  +
  +            // get only a single node as anchor to fetch the owner document
  +            Node n = (Node) this._xpathNodeSet.iterator().next();
  +
  +            this._doc = XMLUtils.getOwnerDocument(n);
  +            this._documentElement = this._doc.getDocumentElement();
  +         }
  +
  +         try {
  +            this._writer = new StringWriter();
  +
  +            this.canonicalizeXPathNodeSet(this._doc);
  +            this._writer.close();
  +
  +            return this._writer.toString();
  +         } catch (IOException ex) {
  +            throw new XMLSignatureException("empty", ex);
  +         } finally {
  +            this._xpathNodeSet = null;
  +            this._doc = null;
  +            this._documentElement = null;
  +            this._writer = null;
  +         }
  +      }
  +
  +      /**
  +       * Method canonicalizeXPathNodeSet
  +       *
  +       * @param currentNode
  +       * @throws XMLSignatureException
  +       */
  +      private void canonicalizeXPathNodeSet(Node currentNode)
  +              throws XMLSignatureException, IOException {
  +
  +         int currentNodeType = currentNode.getNodeType();
  +         boolean currentNodeIsVisible =
  +            this._xpathNodeSet.contains(currentNode);
  +
  +         switch (currentNodeType) {
  +
  +         case Node.DOCUMENT_TYPE_NODE :
  +         default :
  +            break;
  +
  +         case Node.ENTITY_NODE :
  +         case Node.NOTATION_NODE :
  +         case Node.DOCUMENT_FRAGMENT_NODE :
  +         case Node.ATTRIBUTE_NODE :
  +            throw new XMLSignatureException("empty");
  +         case Node.DOCUMENT_NODE :
  +            this._writer.write(HTMLPrefix);
  +
  +            for (Node currentChild = currentNode.getFirstChild();
  +                    currentChild != null;
  +                    currentChild = currentChild.getNextSibling()) {
  +               this.canonicalizeXPathNodeSet(currentChild);
  +            }
  +
  +            this._writer.write(HTMLSuffix);
  +            break;
  +
  +         case Node.COMMENT_NODE :
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            int position = getPositionRelativeToDocumentElement(currentNode);
  +
  +            if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
  +               this._writer.write("\n");
  +            }
  +
  +            this.outputCommentToWriter((Comment) currentNode);
  +
  +            if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
  +               this._writer.write("\n");
  +            }
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +            break;
  +
  +         case Node.PROCESSING_INSTRUCTION_NODE :
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            position = getPositionRelativeToDocumentElement(currentNode);
  +
  +            if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
  +               this._writer.write("\n");
  +            }
  +
  +            this.outputPItoWriter((ProcessingInstruction) currentNode);
  +
  +            if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
  +               this._writer.write("\n");
  +            }
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +            break;
  +
  +         case Node.TEXT_NODE :
  +         case Node.CDATA_SECTION_NODE :
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            outputTextToWriter(currentNode.getNodeValue());
  +
  +            for (Node nextSibling = currentNode.getNextSibling();
  +                    (nextSibling != null)
  +                    && ((nextSibling.getNodeType() == Node.TEXT_NODE)
  +                        || (nextSibling.getNodeType()
  +                            == Node.CDATA_SECTION_NODE));
  +                    nextSibling = nextSibling.getNextSibling()) {
  +
  +               /* The XPath data model allows to select only the first of a
  +                * sequence of mixed text and CDATA nodes. But we must output
  +                * them all, so we must search:
  +                *
  +                * @see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6329
  +                */
  +               this.outputTextToWriter(nextSibling.getNodeValue());
  +            }
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +            break;
  +
  +         case Node.ELEMENT_NODE :
  +            Element currentElement = (Element) currentNode;
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            this._writer.write("&lt;");
  +            this._writer.write(currentElement.getTagName());
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +
  +            // we output all Attrs which are available
  +            NamedNodeMap attrs = currentElement.getAttributes();
  +            int attrsLength = attrs.getLength();
  +            Object attrs2[] = new Object[attrsLength];
  +
  +            for (int i = 0; i < attrsLength; i++) {
  +               attrs2[i] = attrs.item(i);
  +            }
  +
  +            Object attrs3[] =
  +               org.apache.xml.security.c14n.helper.C14nHelper.sortAttributes(
  +                  attrs2);
  +
  +            for (int i = 0; i < attrsLength; i++) {
  +               Attr a = (Attr) attrs3[i];
  +
  +               if (!this._xpathNodeSet.contains(a)) {
  +                  this._writer.write(HTMLExcludePrefix);
  +               }
  +
  +               if (this._inclusiveNamespaces.contains(a.getName())) {
  +                  this._writer.write(HTMLInclusiveNamespacePrefix);
  +               }
  +
  +               this.outputAttrToWriter(a.getNodeName(), a.getNodeValue());
  +
  +               if (this._inclusiveNamespaces.contains(a.getName())) {
  +                  this._writer.write(HTMLInclusiveNamespaceSuffix);
  +               }
  +
  +               if (!this._xpathNodeSet.contains(a)) {
  +                  this._writer.write(HTMLExcludeSuffix);
  +               }
  +            }
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            this._writer.write("&gt;");
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +
  +            // traversal
  +            for (Node currentChild = currentNode.getFirstChild();
  +                    currentChild != null;
  +                    currentChild = currentChild.getNextSibling()) {
  +               this.canonicalizeXPathNodeSet(currentChild);
  +            }
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludePrefix);
  +            }
  +
  +            this._writer.write("&lt;/");
  +            this._writer.write(currentElement.getTagName());
  +            this._writer.write("&gt;");
  +
  +            if (!this._xpathNodeSet.contains(currentNode)) {
  +               this._writer.write(HTMLExcludeSuffix);
  +            }
  +            break;
  +         }
  +      }
  +
  +      /**
  +       * Checks whether a Comment or ProcessingInstruction is before or after the
  +       * document element. This is needed for prepending or appending "\n"s.
  +       *
  +       * @param currentNode comment or pi to check
  +       * @return NODE_BEFORE_DOCUMENT_ELEMENT, NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT or NODE_AFTER_DOCUMENT_ELEMENT
  +       * @see NODE_BEFORE_DOCUMENT_ELEMENT
  +       * @see NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT
  +       * @see NODE_AFTER_DOCUMENT_ELEMENT
  +       */
  +      private int getPositionRelativeToDocumentElement(Node currentNode) {
  +
  +         if (currentNode == null) {
  +            return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
  +         }
  +
  +         Document doc = currentNode.getOwnerDocument();
  +
  +         if (currentNode.getParentNode() != doc) {
  +            return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
  +         }
  +
  +         Element documentElement = doc.getDocumentElement();
  +
  +         if (documentElement == null) {
  +            return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
  +         }
  +
  +         if (documentElement == currentNode) {
  +            return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
  +         }
  +
  +         for (Node x = currentNode; x != null; x = x.getNextSibling()) {
  +            if (x == documentElement) {
  +               return NODE_BEFORE_DOCUMENT_ELEMENT;
  +            }
  +         }
  +
  +         return NODE_AFTER_DOCUMENT_ELEMENT;
  +      }
  +
  +      /**
  +       * Normalizes an {@link Attr}ibute value
  +       *
  +       * The string value of the node is modified by replacing
  +       * <UL>
  +       * <LI>all ampersands (&) with <CODE>&amp;amp;</CODE></LI>
  +       * <LI>all open angle brackets (<) with <CODE>&amp;lt;</CODE></LI>
  +       * <LI>all quotation mark characters with <CODE>&amp;quot;</CODE></LI>
  +       * <LI>and the whitespace characters <CODE>#x9</CODE>, #xA, and #xD, with character
  +       * references. The character references are written in uppercase
  +       * hexadecimal with no leading zeroes (for example, <CODE>#xD</CODE> is represented
  +       * by the character reference <CODE>&amp;#xD;</CODE>)</LI>
  +       * </UL>
  +       *
  +       * @param name
  +       * @param value
  +       * @throws IOException
  +       */
  +      private void outputAttrToWriter(String name, String value)
  +              throws IOException {
  +
  +         this._writer.write(" ");
  +         this._writer.write(name);
  +         this._writer.write("=\"");
  +
  +         int length = value.length();
  +
  +         for (int i = 0; i < length; i++) {
  +            char c = value.charAt(i);
  +
  +            switch (c) {
  +
  +            case '&' :
  +               this._writer.write("&amp;amp;");
  +               break;
  +
  +            case '<' :
  +               this._writer.write("&amp;lt;");
  +               break;
  +
  +            case '"' :
  +               this._writer.write("&amp;quot;");
  +               break;
  +
  +            case 0x09 :    // '\t'
  +               this._writer.write("&amp;#x9;");
  +               break;
  +
  +            case 0x0A :    // '\n'
  +               this._writer.write("&amp;#xA;");
  +               break;
  +
  +            case 0x0D :    // '\r'
  +               this._writer.write("&amp;#xD;");
  +               break;
  +
  +            default :
  +               this._writer.write(c);
  +               break;
  +            }
  +         }
  +
  +         this._writer.write("\"");
  +      }
  +
  +      /**
  +       * Normalizes a {@link org.w3c.dom.Comment} value
  +       *
  +       * @param currentPI
  +       * @throws IOException
  +       */
  +      private void outputPItoWriter(ProcessingInstruction currentPI)
  +              throws IOException {
  +
  +         if (currentPI == null) {
  +            return;
  +         }
  +
  +         this._writer.write("&lt;?");
  +
  +         String target = currentPI.getTarget();
  +         int length = target.length();
  +
  +         for (int i = 0; i < length; i++) {
  +            char c = target.charAt(i);
  +
  +            switch (c) {
  +
  +            case 0x0D :
  +               this._writer.write("&amp;#xD;");
  +               break;
  +
  +            default :
  +               this._writer.write(c);
  +               break;
  +            }
  +         }
  +
  +         String data = currentPI.getData();
  +
  +         length = data.length();
  +
  +         if ((data != null) && (length > 0)) {
  +            this._writer.write(" ");
  +
  +            for (int i = 0; i < length; i++) {
  +               char c = data.charAt(i);
  +
  +               switch (c) {
  +
  +               case 0x0D :
  +                  this._writer.write("&amp;#xD;");
  +                  break;
  +
  +               default :
  +                  this._writer.write(c);
  +                  break;
  +               }
  +            }
  +         }
  +
  +         this._writer.write("?&gt;");
  +      }
  +
  +      /**
  +       * Method outputCommentToWriter
  +       *
  +       * @param currentComment
  +       * @throws IOException
  +       */
  +      private void outputCommentToWriter(Comment currentComment)
  +              throws IOException {
  +
  +         if (currentComment == null) {
  +            return;
  +         }
  +
  +         this._writer.write("&lt;!--");
  +
  +         String data = currentComment.getData();
  +         int length = data.length();
  +
  +         for (int i = 0; i < length; i++) {
  +            char c = data.charAt(i);
  +
  +            switch (c) {
  +
  +            case 0x0D :
  +               this._writer.write("&amp;#xD;");
  +               break;
  +
  +            default :
  +               this._writer.write(c);
  +               break;
  +            }
  +         }
  +
  +         this._writer.write("--&gt;");
  +      }
  +
  +      /**
  +       * Method outputTextToWriter
  +       *
  +       * @param text
  +       * @throws IOException
  +       */
  +      private void outputTextToWriter(String text) throws IOException {
  +
  +         if (text == null) {
  +            return;
  +         }
  +
  +         int length = text.length();
  +
  +         for (int i = 0; i < length; i++) {
  +            char c = text.charAt(i);
  +
  +            switch (c) {
  +
  +            case '&' :
  +               this._writer.write("&amp;amp;");
  +               break;
  +
  +            case '<' :
  +               this._writer.write("&amp;lt;");
  +               break;
  +
  +            case '>' :
  +               this._writer.write("&amp;gt;");
  +               break;
  +
  +            case 0xD :
  +               this._writer.write("&amp;#xD;");
  +               break;
  +
  +            default :
  +               this._writer.write(c);
  +               break;
  +            }
            }
         }
      }