// messageBoard.java // ------------------------------------- // (C) by Michael Peter Christen; mc@anomic.de // first published on http://www.anomic.de // Frankfurt, Germany, 2004 // last major change: 28.06.2004 // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Using this software in any meaning (reading, learning, copying, compiling, // running) means that you agree that the Author(s) is (are) not responsible // for cost, loss of data or any harm that may be caused directly or indirectly // by usage of this softare or this documentation. The usage of this software // is on your own risk. The installation and usage (starting/running) of this // software may allow other people or application to access your computer and // any attached devices and is highly dependent on the configuration of the // software which must be done by the user of the software; the author(s) is // (are) also not responsible for proper configuration and usage of the // software, even if provoked by documentation provided together with // the software. // // Any changes to this file according to the GPL as documented in the file // gpl.txt aside this file in the shipment you received can be done to the // lines that follows this copyright notice here, but changes must not be // done inside the copyright notive above. A re-distribution must contain // the intact and unchanged copyright notice. // Contributions and changes to the program code must be marked as such. package de.anomic.data; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.TimeZone; import de.anomic.kelondro.kelondroBase64Order; import de.anomic.kelondro.kelondroDyn; import de.anomic.kelondro.kelondroMap; public class messageBoard { private static final int categoryLength = 12; private static final String dateFormat = "yyyyMMddHHmmss"; private static final int recordSize = 512; private static TimeZone GMTTimeZone = TimeZone.getTimeZone("PST"); private static SimpleDateFormat SimpleFormatter = new SimpleDateFormat(dateFormat); private kelondroMap database = null; private int sn = 0; public messageBoard(File path, int bufferkb, long preloadTime) { new File(path.getParent()).mkdir(); if (database == null) { database = new kelondroMap(kelondroDyn.open(path, bufferkb * 0x400, preloadTime, categoryLength + dateFormat.length() + 2, recordSize, '_')); } sn = 0; } public int size() { return database.size(); } public int cacheNodeChunkSize() { return database.cacheNodeChunkSize(); } public int cacheObjectChunkSize() { return database.cacheObjectChunkSize(); } public int[] cacheNodeStatus() { return database.cacheNodeStatus(); } public long[] cacheObjectStatus() { return database.cacheObjectStatus(); } public void close() { try {database.close();} catch (IOException e) {} } private static String dateString() { return SimpleFormatter.format(new GregorianCalendar(GMTTimeZone).getTime()); } private String snString() { String s = Integer.toString(sn); if (s.length() == 1) s = "0" + s; sn++; if (sn > 99) sn = 0; return s; } public entry newEntry(String category, String authorName, String authorHash, String recName, String recHash, String subject, byte[] message) { return new entry(category, authorName, authorHash, recName, recHash, subject, message); } public class entry { String key; // composed by category and date Map record; // contains author, target hash, subject and message public entry(String category, String authorName, String authorHash, String recName, String recHash, String subject, byte[] message) { record = new HashMap(); key = category; if (key.length() > categoryLength) key = key.substring(0, categoryLength); while (key.length() < categoryLength) key += "_"; key += dateString() + snString(); if ((authorName == null) || (authorName.length() == 0)) authorName = "anonymous"; record.put("author", authorName); if ((recName == null) || (recName.length() == 0)) recName = "anonymous"; record.put("recipient", recName); if (authorHash == null) authorHash = ""; record.put("ahash", authorHash); if (recHash == null) recHash = ""; record.put("rhash", recHash); if (subject == null) subject = ""; record.put("subject", subject); if (message == null) record.put("message", ""); else record.put("message", kelondroBase64Order.enhancedCoder.encode(message)); record.put("read", "false"); } private entry(String key, Map record) { this.key = key; this.record = record; } public Date date() { try { String c = key.substring(categoryLength); c = c.substring(0, c.length() - 2); return SimpleFormatter.parse(c); } catch (ParseException e) { return new Date(); } } public String category() { String c = key.substring(0, categoryLength); while (c.endsWith("_")) c = c.substring(0, c.length() - 1); return c; } public String author() { String a = (String) record.get("author"); if (a == null) return "anonymous"; return a; } public String recipient() { String a = (String) record.get("recipient"); if (a == null) return "anonymous"; return a; } public String authorHash() { String a = (String) record.get("ahash"); if (a == null) return null; return a; } public String recipientHash() { String a = (String) record.get("rhash"); if (a == null) return null; return a; } public String subject() { String s = (String) record.get("subject"); if (s == null) return ""; return s; } public byte[] message() { String m = (String) record.get("message"); if (m == null) return new byte[0]; record.put("read", "true"); return kelondroBase64Order.enhancedCoder.decode(m); } public boolean read() { String r = (String) record.get("read"); if (r == null) return false; if (r.equals("false")) return false; return true; } } public String write(entry message) { // writes a message and returns key try { database.set(message.key, message.record); return message.key; } catch (IOException e) { return null; } } public entry read(String key) { try { Map record = database.get(key); return new entry(key, record); } catch (IOException e) { return null; } } /* public boolean has(String key) { try { return database.has(key); } catch (IOException e) { return false; } } */ public void remove(String key) { try { database.remove(key); } catch (IOException e) { } } public Iterator keys(String category, boolean up) throws IOException { //return database.keys(); return new catIter(category, up); } public class catIter implements Iterator { Iterator allIter = null; String nextKey = null; String category = ""; public catIter(String category, boolean up) throws IOException { this.allIter = database.keys(up, false); this.category = category; findNext(); } public void findNext() { while (allIter.hasNext()) { nextKey = (String) allIter.next(); if (nextKey.startsWith(this.category)) return; } nextKey = null; } public boolean hasNext() { return nextKey != null; } public Object next() { String next = nextKey; findNext(); return next; } public void remove() { } } }