canonicalizerbase.java
来自「JAVA 所有包」· Java 代码 · 共 880 行 · 第 1/2 页
JAVA
880 行
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */package com.sun.org.apache.xml.internal.security.c14n.implementations;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.ListIterator;import java.util.Set;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;import com.sun.org.apache.xml.internal.security.c14n.CanonicalizerSpi;import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;import com.sun.org.apache.xml.internal.security.signature.NodeFilter;import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;import com.sun.org.apache.xml.internal.security.utils.Constants;import com.sun.org.apache.xml.internal.security.utils.UnsyncByteArrayOutputStream;import com.sun.org.apache.xml.internal.security.utils.XMLUtils;import org.w3c.dom.Attr;import org.w3c.dom.Comment;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NamedNodeMap;import org.w3c.dom.Node;import org.w3c.dom.ProcessingInstruction;import org.xml.sax.SAXException;/** * Abstract base class for canonicalization algorithms. * * @author Christian Geuer-Pollmann <geuerp@apache.org> * @version $Revision: 1.23 $ */public abstract class CanonicalizerBase extends CanonicalizerSpi { //Constants to be outputed, In char array form, so //less garbage is generate when outputed. 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_ = {'&','#','x','A',';'}; private static final byte[] __X9_ = {'&','#','x','9',';'}; private static final byte[] _QUOT_ = {'&','q','u','o','t',';'}; private static final byte[] __XD_ = {'&','#','x','D',';'}; private static final byte[] _GT_ = {'&','g','t',';'}; private static final byte[] _LT_ = {'&','l','t',';'}; private static final byte[] _END_TAG = {'<','/'}; private static final byte[] _AMP_ = {'&','a','m','p',';'}; final static AttrCompare COMPARE=new AttrCompare(); final static String XML="xml"; final static String XMLNS="xmlns"; final static byte[] equalsStr= {'=','\"'}; static final int NODE_BEFORE_DOCUMENT_ELEMENT = -1; static final int NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT = 0; static final int NODE_AFTER_DOCUMENT_ELEMENT = 1; //The null xmlns definiton. protected static final Attr nullNode; static { try { nullNode=DocumentBuilderFactory.newInstance(). newDocumentBuilder().newDocument().createAttributeNS(Constants.NamespaceSpecNS,XMLNS); nullNode.setValue(""); } catch (Exception e) { throw new RuntimeException("Unable to create nullNode"/*,*/+e); } } List nodeFilter; boolean _includeComments; Set _xpathNodeSet = null; /** * The node to be skiped/excluded from the DOM tree * in subtree canonicalizations. */ Node _excludeNode =null; OutputStream _writer = new UnsyncByteArrayOutputStream();//null; /** * Constructor CanonicalizerBase * * @param includeComments */ public CanonicalizerBase(boolean includeComments) { this._includeComments = includeComments; } /** * Method engineCanonicalizeSubTree * @inheritDoc * @param rootNode * @throws CanonicalizationException */ public byte[] engineCanonicalizeSubTree(Node rootNode) throws CanonicalizationException { return engineCanonicalizeSubTree(rootNode,(Node)null); } /** * Canonicalizes a Subtree node. * @param input the root of the subtree to canicalize * @return The canonicalize stream. * @throws CanonicalizationException */ public byte[] engineCanonicalize(XMLSignatureInput input) 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); } } /** * 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 */ byte[] engineCanonicalizeSubTree(Node rootNode,Node excludeNode) 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); } } /** * Method canonicalizeSubTree, this function is a recursive one. * * @param currentNode * @param ns * @param endnode * @throws CanonicalizationException * @throws IOException */ final void canonicalizeSubTree(Node currentNode, NameSpaceSymbTable ns,Node endnode) throws CanonicalizationException, 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); } /** * 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 */ final static int getPositionRelativeToDocumentElement(Node currentNode) { 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; } /** * Method engineCanonicalizeXPathNodeSet * @inheritDoc * @param xpathNodeSet * @throws CanonicalizationException */ public byte[] engineCanonicalizeXPathNodeSet(Set xpathNodeSet) throws CanonicalizationException { this._xpathNodeSet = xpathNodeSet; return engineCanonicalizeXPathNodeSetInternal(XMLUtils.getOwnerDocument(this._xpathNodeSet)); } private byte[] engineCanonicalizeXPathNodeSetInternal(Node doc) throws CanonicalizationException { 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); } } /** * Canoicalizes all the nodes included in the currentNode and contained in the * _xpathNodeSet field. * * @param currentNode * @param endnode * @throws CanonicalizationException * @throws IOException */ final void canonicalizeXPathNodeSet(Node currentNode,Node endnode ) throws CanonicalizationException, 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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?