001/* 002 * Copyright 2015-2024 the original author or authors 003 * 004 * This software is licensed under the Apache License, Version 2.0, 005 * the GNU Lesser General Public License version 2 or later ("LGPL") 006 * and the WTFPL. 007 * You may choose either license to govern your use of this software only 008 * upon the condition that you accept all of the terms of either 009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL. 010 */ 011package org.minidns.record; 012 013import java.io.ByteArrayOutputStream; 014import java.io.DataOutputStream; 015import java.io.IOException; 016import java.io.OutputStream; 017import java.util.Arrays; 018 019import org.minidns.record.Record.TYPE; 020 021/** 022 * Generic payload class. 023 */ 024public abstract class Data { 025 026 /** 027 * The payload type. 028 * @return The payload type. 029 */ 030 public abstract TYPE getType(); 031 032 /** 033 * The internal method used to serialize Data subclasses. 034 * 035 * @param dos the output stream to serialize to. 036 * @throws IOException if an I/O error occurs. 037 */ 038 protected abstract void serialize(DataOutputStream dos) throws IOException; 039 040 private byte[] bytes; 041 042 private void setBytes() { 043 if (bytes != null) return; 044 045 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 046 DataOutputStream dos = new DataOutputStream(baos); 047 try { 048 serialize(dos); 049 } catch (IOException e) { 050 // Should never happen. 051 throw new AssertionError(e); 052 } 053 bytes = baos.toByteArray(); 054 } 055 056 public final int length() { 057 setBytes(); 058 return bytes.length; 059 } 060 061 public final void toOutputStream(OutputStream outputStream) throws IOException { 062 DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 063 toOutputStream(dataOutputStream); 064 } 065 066 /** 067 * Write the binary representation of this payload to the given {@link DataOutputStream}. 068 * 069 * @param dos the DataOutputStream to write to. 070 * @throws IOException if an I/O error occurs. 071 */ 072 public final void toOutputStream(DataOutputStream dos) throws IOException { 073 setBytes(); 074 dos.write(bytes); 075 } 076 077 public final byte[] toByteArray() { 078 setBytes(); 079 return bytes.clone(); 080 } 081 082 private transient Integer hashCodeCache; 083 084 @Override 085 public final int hashCode() { 086 if (hashCodeCache == null) { 087 setBytes(); 088 hashCodeCache = Arrays.hashCode(bytes); 089 } 090 return hashCodeCache; 091 } 092 093 @Override 094 public final boolean equals(Object other) { 095 if (!(other instanceof Data)) { 096 return false; 097 } 098 if (other == this) { 099 return true; 100 } 101 Data otherData = (Data) other; 102 otherData.setBytes(); 103 setBytes(); 104 105 return Arrays.equals(bytes, otherData.bytes); 106 } 107}