001: // messageBoard.java
002: // -------------------------------------
003: // (C) by Michael Peter Christen; mc@anomic.de
004: // first published on http://www.anomic.de
005: // Frankfurt, Germany, 2004
006: // last major change: 28.06.2004
007: //
008: // This program is free software; you can redistribute it and/or modify
009: // it under the terms of the GNU General Public License as published by
010: // the Free Software Foundation; either version 2 of the License, or
011: // (at your option) any later version.
012: //
013: // This program is distributed in the hope that it will be useful,
014: // but WITHOUT ANY WARRANTY; without even the implied warranty of
015: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: // GNU General Public License for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // along with this program; if not, write to the Free Software
020: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: //
022: // Using this software in any meaning (reading, learning, copying, compiling,
023: // running) means that you agree that the Author(s) is (are) not responsible
024: // for cost, loss of data or any harm that may be caused directly or indirectly
025: // by usage of this softare or this documentation. The usage of this software
026: // is on your own risk. The installation and usage (starting/running) of this
027: // software may allow other people or application to access your computer and
028: // any attached devices and is highly dependent on the configuration of the
029: // software which must be done by the user of the software; the author(s) is
030: // (are) also not responsible for proper configuration and usage of the
031: // software, even if provoked by documentation provided together with
032: // the software.
033: //
034: // Any changes to this file according to the GPL as documented in the file
035: // gpl.txt aside this file in the shipment you received can be done to the
036: // lines that follows this copyright notice here, but changes must not be
037: // done inside the copyright notive above. A re-distribution must contain
038: // the intact and unchanged copyright notice.
039: // Contributions and changes to the program code must be marked as such.
040:
041: package de.anomic.data;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.text.ParseException;
046: import java.text.SimpleDateFormat;
047: import java.util.Date;
048: import java.util.HashMap;
049: import java.util.Iterator;
050: import java.util.TimeZone;
051:
052: import de.anomic.kelondro.kelondroBase64Order;
053: import de.anomic.kelondro.kelondroDyn;
054: import de.anomic.kelondro.kelondroMapObjects;
055: import de.anomic.kelondro.kelondroNaturalOrder;
056:
057: public class messageBoard {
058:
059: private static final int categoryLength = 12;
060: private static final String dateFormat = "yyyyMMddHHmmss";
061: private static final int recordSize = 512;
062:
063: private static SimpleDateFormat SimpleFormatter = new SimpleDateFormat(
064: dateFormat);
065:
066: static {
067: SimpleFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
068: }
069:
070: private kelondroMapObjects database = null;
071: private int sn = 0;
072:
073: public messageBoard(File path, long preloadTime) {
074: new File(path.getParent()).mkdir();
075: if (database == null) {
076: database = new kelondroMapObjects(new kelondroDyn(path,
077: true, true, preloadTime, categoryLength
078: + dateFormat.length() + 2, recordSize, '_',
079: kelondroNaturalOrder.naturalOrder, true, false,
080: false), 500);
081: }
082: sn = 0;
083: }
084:
085: public int size() {
086: return database.size();
087: }
088:
089: public void close() {
090: database.close();
091: }
092:
093: private static String dateString() {
094: synchronized (SimpleFormatter) {
095: return SimpleFormatter.format(new Date());
096: }
097: }
098:
099: private String snString() {
100: String s = Integer.toString(sn);
101: if (s.length() == 1)
102: s = "0" + s;
103: sn++;
104: if (sn > 99)
105: sn = 0;
106: return s;
107: }
108:
109: public entry newEntry(String category, String authorName,
110: String authorHash, String recName, String recHash,
111: String subject, byte[] message) {
112: return new entry(category, authorName, authorHash, recName,
113: recHash, subject, message);
114: }
115:
116: public class entry {
117:
118: String key; // composed by category and date
119: HashMap<String, String> record; // contains author, target hash, subject and message
120:
121: public entry(String category, String authorName,
122: String authorHash, String recName, String recHash,
123: String subject, byte[] message) {
124: record = new HashMap<String, String>();
125: key = category;
126: if (key.length() > categoryLength)
127: key = key.substring(0, categoryLength);
128: while (key.length() < categoryLength)
129: key += "_";
130: key += dateString() + snString();
131: if ((authorName == null) || (authorName.length() == 0))
132: authorName = "anonymous";
133: record.put("author", authorName);
134: if ((recName == null) || (recName.length() == 0))
135: recName = "anonymous";
136: record.put("recipient", recName);
137: if (authorHash == null)
138: authorHash = "";
139: record.put("ahash", authorHash);
140: if (recHash == null)
141: recHash = "";
142: record.put("rhash", recHash);
143: if (subject == null)
144: subject = "";
145: record.put("subject", subject);
146: if (message == null)
147: record.put("message", "");
148: else
149: record.put("message", kelondroBase64Order.enhancedCoder
150: .encode(message));
151: record.put("read", "false");
152: }
153:
154: private entry(String key, HashMap<String, String> record) {
155: this .key = key;
156: this .record = record;
157: }
158:
159: public Date date() {
160: try {
161: String c = key.substring(categoryLength);
162: c = c.substring(0, c.length() - 2);
163: synchronized (SimpleFormatter) {
164: return SimpleFormatter.parse(c);
165: }
166: } catch (ParseException e) {
167: return new Date();
168: }
169: }
170:
171: public String category() {
172: String c = key.substring(0, categoryLength);
173: while (c.endsWith("_"))
174: c = c.substring(0, c.length() - 1);
175: return c;
176: }
177:
178: public String author() {
179: String a = record.get("author");
180: if (a == null)
181: return "anonymous";
182: return a;
183: }
184:
185: public String recipient() {
186: String a = record.get("recipient");
187: if (a == null)
188: return "anonymous";
189: return a;
190: }
191:
192: public String authorHash() {
193: String a = record.get("ahash");
194: if (a == null)
195: return null;
196: return a;
197: }
198:
199: public String recipientHash() {
200: String a = record.get("rhash");
201: if (a == null)
202: return null;
203: return a;
204: }
205:
206: public String subject() {
207: String s = record.get("subject");
208: if (s == null)
209: return "";
210: return s;
211: }
212:
213: public byte[] message() {
214: String m = record.get("message");
215: if (m == null)
216: return new byte[0];
217: record.put("read", "true");
218: return kelondroBase64Order.enhancedCoder.decode(m,
219: "de.anomic.data.messageBoard.message()");
220: }
221:
222: public boolean read() {
223: String r = record.get("read");
224: if (r == null)
225: return false;
226: if (r.equals("false"))
227: return false;
228: return true;
229: }
230: }
231:
232: public String write(entry message) {
233: // writes a message and returns key
234: try {
235: database.set(message.key, message.record);
236: return message.key;
237: } catch (IOException e) {
238: return null;
239: }
240: }
241:
242: public entry read(String key) {
243: HashMap<String, String> record = database.getMap(key);
244: return new entry(key, record);
245: }
246:
247: public void remove(String key) {
248: try {
249: database.remove(key);
250: } catch (IOException e) {
251: }
252: }
253:
254: public Iterator<String> keys(String category, boolean up)
255: throws IOException {
256: //return database.keys();
257: return new catIter(category, up);
258: }
259:
260: public class catIter implements Iterator<String> {
261:
262: Iterator<String> allIter = null;
263: String nextKey = null;
264: String category = "";
265:
266: public catIter(String category, boolean up) throws IOException {
267: this .allIter = database.keys(up, false);
268: this .category = category;
269: findNext();
270: }
271:
272: public void findNext() {
273: while (allIter.hasNext()) {
274: nextKey = (String) allIter.next();
275: if (this .category == null
276: || nextKey.startsWith(this .category))
277: return;
278: }
279: nextKey = null;
280: }
281:
282: public boolean hasNext() {
283: return nextKey != null;
284: }
285:
286: public String next() {
287: String next = nextKey;
288: findNext();
289: return next;
290: }
291:
292: public void remove() {
293: }
294:
295: }
296: }
|