All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.util.DigestGenerator Maven / Gradle / Ivy

There is a newer version: 3.1
Show newest version
/*
 * Nuiton Utils %%Ignore-License
 *
 * $Id: DigestGenerator.java 2360 2012-06-11 10:24:36Z tchemit $
 * $HeadURL: http://svn.nuiton.org/svn/nuiton-utils/tags/nuiton-utils-2.6.10/nuiton-utils/src/main/java/org/nuiton/util/DigestGenerator.java $
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */

/*
* Modified by Landais Gabriel, Code Lutin 2008
*
* Works with standard org.w3c.dom XML classes
*
*/

package org.nuiton.util;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Helper class to provide the functionality of the digest value generation. This is an implementation of the DHASH
 * algorithm on .
 * 

* TODO tchemit 2010-08-25 : This class is a nightmare ? we talk about digest mixed with dom nodes ? * TODO tchemit 2010-08-25 : Should have more to explain the purpose (javadoc, author, since...) or (rename | split) this class. */ public class DigestGenerator { public static final String UNICODE_BIG_UNMARKED = "UnicodeBigUnmarked"; /** * This method is an overloaded method for the digest generation for Document * * @param document * @param digestAlgorithm * @return Returns a byte array representing the calculated digest * @throws Exception */ public byte[] getDigest(Document document, String digestAlgorithm) throws Exception { byte[] digest; try { MessageDigest md = MessageDigest.getInstance(digestAlgorithm); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(9); Collection childNodes = getValidElements(document); dos.writeInt(childNodes.size()); for (Object childNode : childNodes) { Node node = (Node) childNode; if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { dos.write(getDigest((ProcessingInstruction) node, digestAlgorithm)); } else if (node.getNodeType() == Node.ELEMENT_NODE) { dos.write(getDigest((Element) node, digestAlgorithm)); } } dos.close(); md.update(baos.toByteArray()); digest = md.digest(); } catch (NoSuchAlgorithmException e) { throw new Exception(e); } catch (IOException e) { throw new Exception(e); } return digest; } /** * This method is an overloaded method for the digest generation for Node * * @param node * @param digestAlgorithm * @return Returns a byte array representing the calculated digest value * @throws Exception */ public byte[] getDigest(Node node, String digestAlgorithm) throws Exception { if (node.getNodeType() == Node.ELEMENT_NODE) { return getDigest((Element) node, digestAlgorithm); } if (node.getNodeType() == Node.TEXT_NODE) { return getDigest((Text) node, digestAlgorithm); } if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { return getDigest((ProcessingInstruction) node, digestAlgorithm); } return new byte[0]; } /** * This method is an overloaded method for the digest generation for Element * * @param element * @param digestAlgorithm * @return Returns a byte array representing the calculated digest value * @throws Exception */ public byte[] getDigest(Element element, String digestAlgorithm) throws Exception { byte[] digest; try { MessageDigest md = MessageDigest.getInstance(digestAlgorithm); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(1); dos.write(getExpandedName(element).getBytes(UNICODE_BIG_UNMARKED)); dos.write((byte) 0); dos.write((byte) 0); Collection attrs = getAttributesWithoutNS(element); dos.writeInt(attrs.size()); for (Object attr : attrs) { dos.write(getDigest((Attr) attr, digestAlgorithm)); } Node node = element.getFirstChild(); // adjoining Texts are merged, // there is no 0-length Text, and // comment nodes are removed. int length = element.getChildNodes().getLength(); dos.writeInt(length); while (node != null) { dos.write(getDigest(node, digestAlgorithm)); node = node.getNextSibling(); } dos.close(); md.update(baos.toByteArray()); digest = md.digest(); } catch (NoSuchAlgorithmException e) { throw new Exception(e); } catch (IOException e) { throw new Exception(e); } return digest; } /** * This method is an overloaded method for the digest generation for ProcessingInstruction * * @param pi * @param digestAlgorithm * @return Returns a byte array representing the calculated digest value * @throws Exception */ public byte[] getDigest(ProcessingInstruction pi, String digestAlgorithm) throws Exception { byte[] digest; try { MessageDigest md = MessageDigest.getInstance(digestAlgorithm); md.update((byte) 0); md.update((byte) 0); md.update((byte) 0); md.update((byte) 7); md.update(pi.getTarget().getBytes(UNICODE_BIG_UNMARKED)); md.update((byte) 0); md.update((byte) 0); md.update(pi.getNodeValue().getBytes(UNICODE_BIG_UNMARKED)); digest = md.digest(); } catch (NoSuchAlgorithmException e) { throw new Exception(e); } catch (UnsupportedEncodingException e) { throw new Exception(e); } return digest; } /** * This method is an overloaded method for the digest generation for Attr * * @param attribute * @param digestAlgorithm * @return Returns a byte array representing the calculated digest value * @throws Exception */ public byte[] getDigest(Attr attribute, String digestAlgorithm) throws Exception { byte[] digest = new byte[0]; if (!(attribute.getLocalName().equals("xmlns") || attribute .getLocalName().startsWith("xmlns:"))) { try { MessageDigest md = MessageDigest.getInstance(digestAlgorithm); md.update((byte) 0); md.update((byte) 0); md.update((byte) 0); md.update((byte) 2); md.update(getExpandedName(attribute).getBytes( UNICODE_BIG_UNMARKED)); md.update((byte) 0); md.update((byte) 0); md.update(attribute.getValue().getBytes(UNICODE_BIG_UNMARKED)); digest = md.digest(); } catch (NoSuchAlgorithmException e) { throw new Exception(e); } catch (UnsupportedEncodingException e) { throw new Exception(e); } } return digest; } /** * This method is an overloaded method for the digest generation for Text * * @param text * @param digestAlgorithm * @return Returns a byte array representing the calculated digest value * @throws Exception */ public byte[] getDigest(Text text, String digestAlgorithm) throws Exception { byte[] digest; try { MessageDigest md = MessageDigest.getInstance(digestAlgorithm); md.update((byte) 0); md.update((byte) 0); md.update((byte) 0); md.update((byte) 3); md.update(text.getTextContent().getBytes(UNICODE_BIG_UNMARKED)); digest = md.digest(); } catch (NoSuchAlgorithmException e) { throw new Exception(e); } catch (UnsupportedEncodingException e) { throw new Exception(e); } return digest; } /** * This method is an overloaded method for getting the expanded name namespaceURI followed by the local name for * Element * * @param element * @return Returns the expanded name of Element */ public String getExpandedName(Element element) { return element.getNamespaceURI() + ":" + element.getLocalName(); } /** * This method is an overloaded method for getting the expanded name namespaceURI followed by the local name for * Attr * * @param attribute * @return Returns the expanded name of the Attr */ public String getExpandedName(Attr attribute) { return attribute.getNamespaceURI() + ":" + attribute.getLocalName(); } /** * Gets the collection of attributes which are none namespace declarations for an Element * * @param element * @return Returns the collection of attributes which are none namespace declarations */ public Collection getAttributesWithoutNS(Element element) { SortedMap map = new TreeMap(); for (int i = 0; i < element.getAttributes().getLength(); i++) { Attr attribute = (Attr) element.getAttributes().item(i); if (!(attribute.getLocalName().equals("xmlns") || attribute .getLocalName().startsWith("xmlns:"))) { map.put(getExpandedName(attribute), attribute); } } return map.values(); } /** * Gets the valid element collection of an Document. Element and ProcessingInstruction only * * @param document * @return Returns a collection of ProcessingInstructions and Elements */ public Collection getValidElements(Document document) { ArrayList list = new ArrayList(); NodeList childNodes = document.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE || node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { list.add(node); } } return list; } /** * Gets the String representation of the byte array * * @param array * @return Returns the String of the byte */ public String getStringRepresentation(byte[] array) { String str = ""; for (byte anArray : array) { str += anArray; } return str; } /** * Compares two Nodes for the XML equality * * @param node * @param comparingNode * @param digestAlgorithm * @return Returns true if the Node XML contents are equal * @throws Exception */ public boolean compareNode(Node node, Node comparingNode, String digestAlgorithm) throws Exception { return Arrays.equals(getDigest(node, digestAlgorithm), getDigest( comparingNode, digestAlgorithm)); } /** * Compares two Documents for the XML equality * * @param document * @param comparingDocument * @param digestAlgorithm * @return Returns true if the Document XML content are equal * @throws Exception */ public boolean compareDocument(Document document, Document comparingDocument, String digestAlgorithm) throws Exception { return Arrays.equals(getDigest(document, digestAlgorithm), getDigest( comparingDocument, digestAlgorithm)); } /** * Compares two Attributes for the XML equality * * @param attribute * @param comparingAttribute * @param digestAlgorithm * @return Returns true if the Document XML content are equal * @throws Exception */ public boolean compareAttribute(Attr attribute, Attr comparingAttribute, String digestAlgorithm) throws Exception { return Arrays.equals(getDigest(attribute, digestAlgorithm), getDigest( comparingAttribute, digestAlgorithm)); } /** String representing the MD5 digest algorithm */ public static final String md5DigestAlgorithm = "MD5"; /** String representing the SHA digest algorithm */ public static final String shaDigestAlgorithm = "SHA"; /** String representing the SHA1 digest algorithm */ public static final String sha1DigestAlgorithm = "SHA1"; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy