FileDocCategorySizeDatePackage
CanonicalizerBase.javaAPI DocJava SE 6 API27276Tue Jun 10 00:23:00 BST 2008com.sun.org.apache.xml.internal.security.c14n.implementations

CanonicalizerBase

public abstract class CanonicalizerBase extends CanonicalizerSpi
Abstract base class for canonicalization algorithms.
author
Christian Geuer-Pollmann
version
$Revision: 1.23 $

Fields Summary
private static final byte[]
_END_PI
private static final byte[]
_BEGIN_PI
private static final byte[]
_END_COMM
private static final byte[]
_BEGIN_COMM
private static final byte[]
__XA_
private static final byte[]
__X9_
private static final byte[]
_QUOT_
private static final byte[]
__XD_
private static final byte[]
_GT_
private static final byte[]
_LT_
private static final byte[]
_END_TAG
private static final byte[]
_AMP_
static final AttrCompare
COMPARE
static final String
XML
static final String
XMLNS
static final byte[]
equalsStr
static final int
NODE_BEFORE_DOCUMENT_ELEMENT
static final int
NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT
static final int
NODE_AFTER_DOCUMENT_ELEMENT
protected static final Attr
nullNode
List
nodeFilter
boolean
_includeComments
Set
_xpathNodeSet
Node
_excludeNode
The node to be skiped/excluded from the DOM tree in subtree canonicalizations.
OutputStream
_writer
Constructors Summary
public CanonicalizerBase(boolean includeComments)
Constructor CanonicalizerBase

param
includeComments

//null;

           
      
      this._includeComments = includeComments;
   
Methods Summary
final voidcanonicalizeSubTree(org.w3c.dom.Node currentNode, com.sun.org.apache.xml.internal.security.c14n.implementations.NameSpaceSymbTable ns, org.w3c.dom.Node endnode)
Method canonicalizeSubTree, this function is a recursive one.

param
currentNode
param
ns
param
endnode
throws
CanonicalizationException
throws
IOException

    	Node sibling=null;
    	Node parentNode=null;
    	final OutputStream writer=this._writer;
    	final Node excludeNode=this._excludeNode;
    	final boolean includeComments=this._includeComments;
    	do {
    		switch (currentNode.getNodeType()) {
    		
    		case Node.DOCUMENT_TYPE_NODE :
    		default :
    			break;
    		
    		case Node.ENTITY_NODE :
    		case Node.NOTATION_NODE :
    		case Node.ATTRIBUTE_NODE :
    			// illegal node type during traversal
    			throw new CanonicalizationException("empty");

            case Node.DOCUMENT_FRAGMENT_NODE :
    		case Node.DOCUMENT_NODE :
    			ns.outputNodePush();
    			//currentNode = currentNode.getFirstChild();  
    			sibling= currentNode.getFirstChild();
    			break;
    			
    		case Node.COMMENT_NODE :
    			if (includeComments) {
    				outputCommentToWriter((Comment) currentNode, writer);
    			}
    			break;
    			
    		case Node.PROCESSING_INSTRUCTION_NODE :
    			outputPItoWriter((ProcessingInstruction) currentNode, writer);
    			break;
    			
    		case Node.TEXT_NODE :
    		case Node.CDATA_SECTION_NODE :
    			outputTextToWriter(currentNode.getNodeValue(), writer);
    			break;
    			
    		case Node.ELEMENT_NODE :        
    			if (currentNode==excludeNode) {
    				break;
    			}      
    			Element currentElement = (Element) currentNode;
    			//Add a level to the nssymbtable. So latter can be pop-back.
    			ns.outputNodePush();
    			writer.write('<");
    			String name=currentElement.getTagName();
    			writeStringToUtf8(name,writer);
    			
    			Iterator attrs = this.handleAttributesSubtree(currentElement,ns);
    			if (attrs!=null) {
    				//we output all Attrs which are available
    				while (attrs.hasNext()) {
    					Attr attr = (Attr) attrs.next();
    					outputAttrToWriter(attr.getNodeName(),attr.getNodeValue(), writer);
    				}
    			}
    			writer.write('>");        
    			sibling= currentNode.getFirstChild(); 
    			if (sibling==null) {
    				writer.write(_END_TAG);
        			writeStringToUtf8(name,writer);        
        			writer.write('>");
        			//We fineshed with this level, pop to the previous definitions.
        			ns.outputNodePop();
				if (parentNode != null) {
       			    		sibling= currentNode.getNextSibling();
				}
    			} else {
    				parentNode=currentElement;
    			}
    			break;
    		}
    		while (sibling==null  && parentNode!=null) {    		      		      			
    			writer.write(_END_TAG);
    			writeStringToUtf8(((Element)parentNode).getTagName(),writer);        
    			writer.write('>");
    			//We fineshed with this level, pop to the previous definitions.
    			ns.outputNodePop();
    			if (parentNode==endnode)
    				return;
    			sibling=parentNode.getNextSibling();
    			parentNode=parentNode.getParentNode();   
    			if (!(parentNode instanceof Element)) {
    				parentNode=null;
    			}    			
    		}      
    		if (sibling==null)
    			return;
    		currentNode=sibling;      
    		sibling=currentNode.getNextSibling();  
    	} while(true);
    
final voidcanonicalizeXPathNodeSet(org.w3c.dom.Node currentNode, org.w3c.dom.Node endnode)
Canoicalizes all the nodes included in the currentNode and contained in the _xpathNodeSet field.

param
currentNode
param
endnode
throws
CanonicalizationException
throws
IOException

	   boolean currentNodeIsVisible = false;	  
	   NameSpaceSymbTable ns=new  NameSpaceSymbTable();
  	Node sibling=null;
	Node parentNode=null;	
	OutputStream writer=this._writer;
	do {
		switch (currentNode.getNodeType()) {
		
		case Node.DOCUMENT_TYPE_NODE :
		default :
			break;
		
		case Node.ENTITY_NODE :
		case Node.NOTATION_NODE :
		case Node.ATTRIBUTE_NODE :
			// illegal node type during traversal
			throw new CanonicalizationException("empty");

        case Node.DOCUMENT_FRAGMENT_NODE :
		case Node.DOCUMENT_NODE :
			ns.outputNodePush();
			//currentNode = currentNode.getFirstChild();  
			sibling= currentNode.getFirstChild();
			break;
			
		case Node.COMMENT_NODE :			
			if (this._includeComments && isVisible(currentNode)) {
				outputCommentToWriter((Comment) currentNode, writer);
			}
			break;
			
		case Node.PROCESSING_INSTRUCTION_NODE :
			if (isVisible(currentNode))
				outputPItoWriter((ProcessingInstruction) currentNode, writer);
			break;
			
		case Node.TEXT_NODE :
		case Node.CDATA_SECTION_NODE :
			if (isVisible(currentNode)) {
			outputTextToWriter(currentNode.getNodeValue(), writer);
			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
                */
               outputTextToWriter(nextSibling.getNodeValue(), writer);
               currentNode=nextSibling;
               sibling=currentNode.getNextSibling();
            }
			
			}
			break;
			
		case Node.ELEMENT_NODE :             
			Element currentElement = (Element) currentNode;
			//Add a level to the nssymbtable. So latter can be pop-back.
			String name=null;
			currentNodeIsVisible=isVisible(currentNode);
			if (currentNodeIsVisible) {
				ns.outputNodePush();
				writer.write('<");
				name=currentElement.getTagName();
				writeStringToUtf8(name,writer);
			} else {
				ns.push();
			}
			
			Iterator attrs = handleAttributes(currentElement,ns);
			if (attrs!=null) {
				//we output all Attrs which are available
				while (attrs.hasNext()) {
					Attr attr = (Attr) attrs.next();
					outputAttrToWriter(attr.getNodeName(),attr.getNodeValue(), writer);
				}
			}
			if (currentNodeIsVisible) {
				writer.write('>");
			}
			sibling= currentNode.getFirstChild(); 
		
			if (sibling==null) {
				if (currentNodeIsVisible) {
					writer.write(_END_TAG);
					writeStringToUtf8(name,writer);        
					writer.write('>");
					//We fineshed with this level, pop to the previous definitions.
					ns.outputNodePop();
				} else {
					ns.pop();
				}				
				if (parentNode != null) {
    					sibling= currentNode.getNextSibling();
				}
			} else {
				parentNode=currentElement;
			}
			break;
		}
		while (sibling==null  && parentNode!=null) {    
			if (isVisible(parentNode)) {
				writer.write(_END_TAG);
				writeStringToUtf8(((Element)parentNode).getTagName(),writer);        
				writer.write('>");
				//We fineshed with this level, pop to the previous definitions.
				ns.outputNodePop();
			} else {
				ns.pop();
			}
			if (parentNode==endnode)
				return;
			sibling=parentNode.getNextSibling();
			parentNode=parentNode.getParentNode();   
			if (!(parentNode instanceof Element)) {
				parentNode=null;
			}    			
		}      
		if (sibling==null)
			return;
		currentNode=sibling;      
		sibling=currentNode.getNextSibling();  
	} while(true);
   
public byte[]engineCanonicalize(com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput input)
Canonicalizes a Subtree node.

param
input the root of the subtree to canicalize
return
The canonicalize stream.
throws
CanonicalizationException

    	try {
    		if (input.isExcludeComments())
    			_includeComments = false;
			byte[] bytes;
			if (input.isOctetStream()) {
				return engineCanonicalize(input.getBytes());
			}
			if (input.isElement()) {
				bytes = engineCanonicalizeSubTree(input.getSubNode(), input
						.getExcludeNode());
				return bytes;
			} else if (input.isNodeSet()) {
				nodeFilter=input.getNodeFilters();
                                Document doc = null;
                                if (input.getSubNode() != null) {
                                    doc=XMLUtils.getOwnerDocument(input.getSubNode());
                                } else {
                                    doc=XMLUtils.getOwnerDocument(input.getNodeSet());
                                }
				if (input.isNeedsToBeExpanded()) {
					XMLUtils.circumventBug2650(doc);
				}

				if (input.getSubNode() != null) {
				    bytes = engineCanonicalizeXPathNodeSetInternal(input.getSubNode());
				} else {
				    bytes = engineCanonicalizeXPathNodeSet(input.getNodeSet());
				}
				return bytes;

			}
			return null;
		} catch (CanonicalizationException ex) {
			throw new CanonicalizationException("empty", ex);
		} catch (ParserConfigurationException ex) {
			throw new CanonicalizationException("empty", ex);
		} catch (IOException ex) {
			throw new CanonicalizationException("empty", ex);
		} catch (SAXException ex) {
			throw new CanonicalizationException("empty", ex);
		}
   
public byte[]engineCanonicalizeSubTree(org.w3c.dom.Node rootNode)
Method engineCanonicalizeSubTree

inheritDoc
param
rootNode
throws
CanonicalizationException

   		return engineCanonicalizeSubTree(rootNode,(Node)null);
   
byte[]engineCanonicalizeSubTree(org.w3c.dom.Node rootNode, org.w3c.dom.Node excludeNode)
Canonicalizes a Subtree node.

param
rootNode the root of the subtree to canicalize
param
excludeNode a node to be excluded from the canicalize operation
return
The canonicalize stream.
throws
CanonicalizationException

    	this._excludeNode = excludeNode;
        try {
         NameSpaceSymbTable ns=new NameSpaceSymbTable();
         if (rootNode instanceof Element) {
         	//Fills the nssymbtable with the definitions of the parent of the root subnode
         	getParentNameSpaces((Element)rootNode,ns);
         }         
         this.canonicalizeSubTree(rootNode,ns,rootNode);
         this._writer.close();
         if (this._writer instanceof ByteArrayOutputStream) {
            byte []result=((ByteArrayOutputStream)this._writer).toByteArray();
            if (reset) {
                ((ByteArrayOutputStream)this._writer).reset();        
            }
         	return result;
         } 
         return null;
         
      } catch (UnsupportedEncodingException ex) {
         throw new CanonicalizationException("empty", ex);
      } catch (IOException ex) {
         throw new CanonicalizationException("empty", ex);
      } 
   
public byte[]engineCanonicalizeXPathNodeSet(java.util.Set xpathNodeSet)
Method engineCanonicalizeXPathNodeSet

inheritDoc
param
xpathNodeSet
throws
CanonicalizationException

	   this._xpathNodeSet = xpathNodeSet;
	   return engineCanonicalizeXPathNodeSetInternal(XMLUtils.getOwnerDocument(this._xpathNodeSet));
   
private byte[]engineCanonicalizeXPathNodeSetInternal(org.w3c.dom.Node doc)

   
      
      try { 
         this.canonicalizeXPathNodeSet(doc,doc);
         this._writer.close();
         if (this._writer instanceof ByteArrayOutputStream) {
            byte [] sol=((ByteArrayOutputStream)this._writer).toByteArray();
            if (reset) {
            	((ByteArrayOutputStream)this._writer).reset();
            }
         	return sol;
         }
         return null;
      } catch (UnsupportedEncodingException ex) {
         throw new CanonicalizationException("empty", ex);
      } catch (IOException ex) {
         throw new CanonicalizationException("empty", ex);
      } 
   
static final voidgetParentNameSpaces(org.w3c.dom.Element el, com.sun.org.apache.xml.internal.security.c14n.implementations.NameSpaceSymbTable ns)
Adds to ns the definitons from the parent elements of el

param
el
param
ns

   		List parents=new ArrayList();
   		Node n1=el.getParentNode();
   		if (!(n1 instanceof Element)) {
   			return;
   		}
   		//Obtain all the parents of the elemnt
   		Element parent=(Element) el.getParentNode();
   		while (parent!=null) {
   			parents.add(parent);
   			Node n=parent.getParentNode();
   			if (!(n instanceof Element )) {
   				break;
   			}
   			parent=(Element)n;
   		}
   		//Visit them in reverse order.
   		ListIterator it=parents.listIterator(parents.size());
   		while (it.hasPrevious()) {
   		Element ele=(Element)it.previous();
        if (!ele.hasAttributes()) {
        	continue;
        }
		NamedNodeMap attrs = ele.getAttributes();
   		int attrsLength = attrs.getLength();
   		 for (int i = 0; i < attrsLength; i++) {
            Attr N = (Attr) attrs.item(i);
            if (!Constants.NamespaceSpecNS.equals(N.getNamespaceURI())) {
               //Not a namespace definition, ignore.
               continue;
            }

            String NName=N.getLocalName();
            String NValue=N.getNodeValue();
            if (XML.equals(NName)
                    && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
               continue;
            }            
            ns.addMapping(NName,NValue,N);             
   		 }   			
   		}
        Attr nsprefix;
        if (((nsprefix=ns.getMappingWithoutRendered("xmlns"))!=null) 
                && "".equals(nsprefix.getValue())) {
             ns.addMappingAndRender("xmlns","",nullNode);
        }
   	
static final intgetPositionRelativeToDocumentElement(org.w3c.dom.Node currentNode)
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

            
      if ((currentNode == null) || 
            (currentNode.getParentNode().getNodeType() != Node.DOCUMENT_NODE) ) {
         return CanonicalizerBase.NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
      }
      Element documentElement = currentNode.getOwnerDocument().getDocumentElement();
      if ( (documentElement == null)  || (documentElement == currentNode) ){
         return CanonicalizerBase.NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
      }
      
      for (Node x = currentNode; x != null; x = x.getNextSibling()) {
         if (x == documentElement) {
            return CanonicalizerBase.NODE_BEFORE_DOCUMENT_ELEMENT;
         }
      }

      return CanonicalizerBase.NODE_AFTER_DOCUMENT_ELEMENT;
   
abstract java.util.IteratorhandleAttributes(org.w3c.dom.Element E, com.sun.org.apache.xml.internal.security.c14n.implementations.NameSpaceSymbTable ns)
Obtain the attributes to output for this node in XPathNodeSet c14n.

param
E
param
ns
return
the attributes nodes to output.
throws
CanonicalizationException

abstract java.util.IteratorhandleAttributesSubtree(org.w3c.dom.Element E, com.sun.org.apache.xml.internal.security.c14n.implementations.NameSpaceSymbTable ns)
Obtain the attributes to output for this node in a Subtree c14n.

param
E
param
ns
return
the attributes nodes to output.
throws
CanonicalizationException

booleanisVisible(org.w3c.dom.Node currentNode)

	   if (nodeFilter!=null) {
   		Iterator it=nodeFilter.iterator();
   		while (it.hasNext()) {
   			if (!((NodeFilter)it.next()).isNodeInclude(currentNode))
   				return false;
   		}
	   }
   		if ((this._xpathNodeSet!=null) && !this._xpathNodeSet.contains(currentNode))
   			return false;
   		return true;
   	
static final voidoutputAttrToWriter(java.lang.String name, java.lang.String value, java.io.OutputStream writer)
Outputs an Attribute to the internal Writer. The string value of the node is modified by replacing
  • all ampersands (&) with &amp;
  • all open angle brackets (<) with &lt;
  • all quotation mark characters with &quot;
  • and the whitespace characters #x9, #xA, and #xD, with character references. The character references are written in uppercase hexadecimal with no leading zeroes (for example, #xD is represented by the character reference &#xD;)

param
name
param
value
param
writer
throws
IOException

      writer.write(' ");
      writeStringToUtf8(name,writer);
      writer.write(equalsStr);
      byte  []toWrite;
      final int length = value.length();
      for (int i=0;i < length; i++) {        
         char c = value.charAt(i);

         switch (c) {

         case '&" :
         	toWrite=_AMP_;
            //writer.write(_AMP_);
            break;

         case '<" :
         	toWrite=_LT_;
            //writer.write(_LT_);
            break;

         case '"" :
         	toWrite=_QUOT_;
            //writer.write(_QUOT_);
            break;

         case 0x09 :    // '\t'
         	toWrite=__X9_;
            //writer.write(__X9_);
            break;

         case 0x0A :    // '\n'
         	toWrite=__XA_;
            //writer.write(__XA_);
            break;

         case 0x0D :    // '\r'
         	toWrite=__XD_;
            //writer.write(__XD_);
            break;

         default :
            writeCharToUtf8(c,writer);
            //this._writer.write(c);
            continue;
         }
         writer.write(toWrite);
      }

      writer.write('\"");
   
static final voidoutputCommentToWriter(org.w3c.dom.Comment currentComment, java.io.OutputStream writer)
Method outputCommentToWriter

param
currentComment
param
writer writer where to write the things
throws
IOException

   	  final int position = getPositionRelativeToDocumentElement(currentComment);
   	  if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
   		writer.write('\n");
   	  }
      writer.write(_BEGIN_COMM);

      final String data = currentComment.getData();
      final int length = data.length();      

      for (int i = 0; i < length; i++) {         
         char c=data.charAt(i);
         if (c==0x0D) {
            writer.write(__XD_);
         } else {
            writeCharToUtf8(c,writer);               
         }      
      }

      writer.write(_END_COMM);
      if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
		writer.write('\n");
	 }
   
static final voidoutputPItoWriter(org.w3c.dom.ProcessingInstruction currentPI, java.io.OutputStream writer)
Outputs a PI to the internal Writer.

param
currentPI
param
writer where to write the things
throws
IOException

   	  final int position = getPositionRelativeToDocumentElement(currentPI);

      if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
        writer.write('\n");
      }
      writer.write(_BEGIN_PI);

      final String target = currentPI.getTarget();
      int length = target.length();

      for (int i = 0; i < length; i++) {         
      	 char c=target.charAt(i);
         if (c==0x0D) {
            writer.write(__XD_);
         } else {
            writeCharToUtf8(c,writer);            
         }
      }

      final String data = currentPI.getData();
     
      length = data.length();

      if (length > 0) {
         writer.write(' ");

         for (int i = 0; i < length; i++) {            
         	char c=data.charAt(i);
            if (c==0x0D) {
               writer.write(__XD_);
            } else {
               writeCharToUtf8(c,writer);               
            }
         }
      }

      writer.write(_END_PI);
      if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
        writer.write('\n");
     }
   
static final voidoutputTextToWriter(java.lang.String text, java.io.OutputStream writer)
Outputs a Text of CDATA section to the internal Writer.

param
text
param
writer writer where to write the things
throws
IOException

      final int length = text.length();
      byte []toWrite;
      for (int i = 0; i < length; i++) {
         char c = text.charAt(i);

         switch (c) {

         case '&" :
         	toWrite=_AMP_;
            //writer.write(_AMP_);
            break;

         case '<" :
         	toWrite=_LT_;
            //writer.write(_LT_);
            break;

         case '>" :
         	toWrite=_GT_;
            //writer.write(_GT_);
            break;

         case 0xD :
         	toWrite=__XD_;
            //writer.write(__XD_);
            break;

         default :
            writeCharToUtf8(c,writer);
            continue;
         }
         writer.write(toWrite);
      }
   
public voidsetWriter(java.io.OutputStream _writer)

param
_writer The _writer to set.

    	this._writer = _writer;
    
static final voidwriteCharToUtf8(char c, java.io.OutputStream out)

   	char ch;
   	if (/*(c >= 0x0001) &&*/ (c <= 0x007F)) {
        out.write(c);
        return;
    }
    int bias;
    int write;
    if (c > 0x07FF) {
        ch=(char)(c>>>12);      
        write=0xE0;
        if (ch>0) {
            write |= ( ch & 0x0F);
        } 
        out.write(write);
        write=0x80;
        bias=0x3F;        
    } else {
    	write=0xC0;
    	bias=0x1F;
    }
    ch=(char)(c>>>6);
    if (ch>0) {
         write|= (ch & bias);
    } 
    out.write(write);
    out.write(0x80 | ((c) & 0x3F));    
   	
   
static final voidwriteStringToUtf8(java.lang.String str, java.io.OutputStream out)

   	final int length=str.length();
   	int i=0;
    char c;    
   	while (i<length) {
   		c=str.charAt(i++);        
        if (/*(c >= 0x0001) &&*/ (c <= 0x007F)) {
            out.write(c);
            continue;
        }
        char ch;
        int bias;
        int write;
        if (c > 0x07FF) {
            ch=(char)(c>>>12);      
            write=0xE0;
            if (ch>0) {
                write |= ( ch & 0x0F);
            } 
            out.write(write);
            write=0x80;
            bias=0x3F;        
        } else {
        	write=0xC0;
        	bias=0x1F;
        }
        ch=(char)(c>>>6);
        if (ch>0) {
             write|= (ch & bias);
        } 
        out.write(write);
        out.write(0x80 | ((c) & 0x3F));
        continue;         
           		
   	}