package org.torrent.basnark.bencode; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * Date: 22.09.2009 * Time: 21:23:05 (Moscow Standard Time) * * @author Vlad Vinichenko (akerigan@gmail.com) */ @SuppressWarnings({"unchecked"}) public class BEntry { private Object content; public BEntry() { } public BEntry(BigDecimal number) { this.content = number; } public BEntry(byte[] byteArray) { this.content = byteArray; } public BigDecimal getNumber() { if (content instanceof BigDecimal) { return (BigDecimal) content; } else { return null; } } public void setNumber(BigDecimal number) { this.content = number; } public byte[] getByteArray() { if (content instanceof byte[]) { return (byte[]) content; } else { return null; } } public void setByteArray(byte[] byteArray) { this.content = byteArray; } public List<BEntry> getList() { if (content instanceof List) { return (List<BEntry>) content; } else { return null; } } public void addEntry(BEntry entry) { if (content == null) { content = new ArrayList<BEntry>(); } ((List<BEntry>) content).add(entry); } public Map<String, BEntry> getMap() { if (content instanceof Map) { return (Map<String, BEntry>) content; } else { return null; } } public void putEntry(String key, BEntry value) { if (content == null) { content = new LinkedHashMap<String, BEntry>(); } ((Map<String, BEntry>) content).put(key, value); } public static BEntry readEntry(InputStream in) throws IOException { return readEntry(new BEncodedStreamReader(in)); } public static BEntry readEntry(BEncodedStreamReader reader) throws IOException { BEntry entry = new BEntry(); if (reader.hasNext()) { switch (reader.next()) { case BEncodedStreamReader.DICTIONARY_START: BEntry keyEntry; do { keyEntry = readEntry(reader); if (keyEntry != null) { entry.putEntry(new String(keyEntry.getByteArray()), readEntry(reader)); } } while (keyEntry != null); return entry; case BEncodedStreamReader.DICTIONARY_END: return null; case BEncodedStreamReader.LIST_START: BEntry newEntry; do { newEntry = readEntry(reader); if (newEntry != null) { entry.addEntry(newEntry); } } while (newEntry != null); return entry; case BEncodedStreamReader.LIST_END: return null; case BEncodedStreamReader.INTEGER: entry.setNumber(reader.getNumber()); return entry; case BEncodedStreamReader.BYTE_ARRAY: entry.setByteArray(reader.getByteArray()); return entry; } } return entry; } public void serialize(OutputStream outputStream) throws IOException { if (content != null) { if (content instanceof BigDecimal) { outputStream.write('i'); serializeNumber((BigDecimal) content, outputStream); outputStream.write('e'); } else if (content instanceof byte[]) { serializeByteArray((byte[]) content, outputStream); } else if (content instanceof List) { outputStream.write('l'); for (BEntry bEntry : (List<BEntry>) content) { bEntry.serialize(outputStream); } outputStream.write('e'); } else if (content instanceof Map) { outputStream.write('d'); for (Map.Entry<String, BEntry> entry : ((Map<String, BEntry>) content).entrySet()) { serializeByteArray(entry.getKey().getBytes(), outputStream); entry.getValue().serialize(outputStream); } outputStream.write('e'); } } } private void serializeByteArray(byte[] bytes, OutputStream outputStream) throws IOException { if (bytes != null) { serializeNumber(new BigDecimal(bytes.length), outputStream); outputStream.write(':'); outputStream.write(bytes); } } private void serializeNumber(BigDecimal number, OutputStream outputStream) throws IOException { if (number != null) { String value = number.toString(); for (int i = 0; i < value.length(); ++i) { outputStream.write(value.charAt(i)); } } } @Override public String toString() { if (content != null) { if (content instanceof BigDecimal || content instanceof List || content instanceof Map) { return content.toString(); } else if (content instanceof byte[]) { return new String((byte[]) content); } } return ""; } }