/*
* XCTrack - XContest Live Tracking client for J2ME devices
* Copyright (C) 2009 Petr Chromec <petr@xcontest.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
package org.xcontest.xctrack.util;
import java.util.Calendar;
import java.util.Vector;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
class LogRecordComparator implements RecordComparator {
public int compare(byte[] a, byte[] b) {
// the first 4 bytes are (int)sequence
if (a.length < 4 || b.length < 4) {
return EQUIVALENT;
}
for (int i = 0; i < 4; i ++) {
int ai = ((int)a[i]+256)%256;
int bi = ((int)b[i]+256)%256;
if (ai < bi) return PRECEDES;
if (ai > bi) return FOLLOWS;
}
return EQUIVALENT;
}
}
public final class Log {
private static LogListener _listener = null;
private static Vector _rsRecords = null;
private static int _rsNextSeq = 0;
private static final int LOG_SIZE = 50; // number of messages
public static void info(String msg) {
append(LogRecord.INFO,msg);
}
public static void debug(String msg) {
append(LogRecord.DEBUG,msg);
}
public static void error(String msg) {
append(LogRecord.ERROR,msg);
}
public static void error(String msg, Throwable e) {
append(LogRecord.ERROR,msg + "[EX:"+e.getClass().getName()+":"+e.getMessage()+"]");
}
public static synchronized void setListener(LogListener l) {
_listener = l;
}
public synchronized static LogRecord[] readAll() {
if (_rsRecords == null) {
try {
RecordStore rs = openRS();
rs.closeRecordStore();
}
catch (RecordStoreException e) {
// Util.showError("Cannot read log",e);
}
}
LogRecord[] out = new LogRecord[_rsRecords.size()];
for (int i = 0; i < out.length; i ++) {
out[i] = (LogRecord)_rsRecords.elementAt(i);
}
return out;
}
public synchronized static void clear() {
try {
RecordStore.deleteRecordStore("log");
}
catch (Exception e) {
}
_rsRecords = null;
}
private synchronized static RecordStore openRS() throws RecordStoreException {
RecordStore rs = RecordStore.openRecordStore("log", true);
// read _rsSeqToRecord hash and initialize the _rsNextSeq
if (_rsRecords == null) {
RecordEnumeration re;
_rsNextSeq = 1;
try {
re = rs.enumerateRecords(null, new LogRecordComparator(), false);
}
catch (Exception e) {
rs.closeRecordStore();
RecordStore.deleteRecordStore("log");
rs = RecordStore.openRecordStore("log", true);
re = rs.enumerateRecords(null, new LogRecordComparator(), false);
}
_rsRecords = new Vector();
while (re.hasNextElement()) {
int id = re.nextRecordId();
LogRecord rec = new LogRecord(id,rs.getRecord(id));
int seq = rec.getSeq();
if (_rsNextSeq <= seq)
_rsNextSeq = seq + 1;
_rsRecords.addElement(rec);
}
}
return rs;
}
private synchronized static void append(int type, String msg) {
LogRecord rec = new LogRecord(_rsNextSeq,Calendar.getInstance().getTime().getTime(),type,msg);
if (_listener != null)
_listener.newLogRecord(rec);
RecordStore rs = null;
try {
rs = openRS();
// delete the oldest record if LOG_SIZE is reached
while (_rsRecords.size() > LOG_SIZE) {
rs.deleteRecord(((LogRecord)_rsRecords.elementAt(0)).getRecordStoreId());
_rsRecords.removeElementAt(0);
}
// push new record to the record store and cache
int id = rs.addRecord(rec.getData(),0,rec.getData().length);
rec.setRecordStoreId(id);
_rsRecords.addElement(rec);
_rsNextSeq ++;
}
catch (RecordStoreException e) {
}
finally {
try {
if (rs != null)
rs.closeRecordStore();
}
catch(RecordStoreException e) {
}
}
}
}