
org.nuiton.util.DigestGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nuiton-utils Show documentation
Show all versions of nuiton-utils Show documentation
Library of usefull class to be used in any project.
/*
* 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