001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.space; 020 021import java.io.Serializable; 022import java.io.IOException; 023import java.io.ByteArrayOutputStream; 024import java.io.ObjectOutputStream; 025import java.security.MessageDigest; 026import java.util.Arrays; 027 028import org.jpos.iso.ISOUtil; 029 030/** 031 * Space {@link Template} that compares entries by an MD5 digest of their 032 * serialized form rather than by reference equality. 033 */ 034public class MD5Template implements Template, Serializable { 035 private static final long serialVersionUID = -1204861759575740048L; 036 /** Digest of the serialized comparison value. */ 037 byte[] digest; 038 /** Key associated with this template. */ 039 Object key; 040 041 /** 042 * Constructs a template that matches entries whose serialized form digests to {@code value}. 043 * 044 * @param key entry key 045 * @param value reference value to digest 046 */ 047 public MD5Template (Object key, Object value) { 048 super (); 049 this.key = key; 050 this.digest = digest (value); 051 } 052 /** 053 * Constructs a template directly from a precomputed digest. 054 * 055 * @param key entry key 056 * @param digest precomputed MD5 digest 057 */ 058 public MD5Template (Object key, byte[] digest) { 059 super (); 060 this.key = key; 061 this.digest = digest; 062 } 063 /** 064 * Computes the MD5 digest of {@code obj}'s serialized form. 065 * 066 * @param obj object to digest 067 * @return the MD5 digest bytes 068 */ 069 public byte[] digest (Object obj) { 070 try { 071 MessageDigest md = MessageDigest.getInstance ("MD5"); 072 return md.digest (serialize (obj)); 073 } catch (Exception e) { 074 throw new SpaceError (e); 075 } 076 } 077 @Override 078 public boolean equals (Object obj) { 079 return Arrays.equals (digest (obj), digest); 080 } 081 @Override 082 public int hashCode() { 083 assert false : "hashCode not designed"; 084 return 42; 085 } 086 /** 087 * Returns the key this template is registered under. 088 * 089 * @return the entry key 090 */ 091 public Object getKey () { 092 return key; 093 } 094 /** 095 * Returns the digest used for comparison. 096 * 097 * @return the MD5 digest bytes 098 */ 099 public byte[] getDigest () { 100 return digest; 101 } 102 /** 103 * Returns the digest as a hex-encoded string. 104 * 105 * @return the digest hex string 106 */ 107 public String getDigestAsString () { 108 return ISOUtil.hexString (digest); 109 } 110 public String toString () { 111 StringBuilder sb = new StringBuilder(); 112 sb.append ("key='"); 113 sb.append (key); 114 sb.append ("', digest="); 115 sb.append (getDigestAsString ()); 116 return sb.toString(); 117 } 118 /** 119 * Serializes {@code obj} via {@link ObjectOutputStream}, returning the resulting bytes. 120 * 121 * @param obj object to serialize 122 * @return the serialized byte array 123 * @throws IOException if writing fails 124 */ 125 public static byte[] serialize (Object obj) throws IOException { 126 ByteArrayOutputStream baos; 127 ObjectOutputStream oos; 128 129 baos = new ByteArrayOutputStream(); 130 oos = new ObjectOutputStream (baos); 131 oos.writeObject (obj); 132 oos.close(); 133 134 return baos.toByteArray(); 135 } 136}