package jimm.history; import jimm.Jimm; import jimm.comm.StringUtils; import jimm.comm.Util; import ru.net.jimm.config.HomeDirectory; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created with IntelliJ IDEA. * <p/> * Date: 15.12.12 18:35 * * @author vladimir */ public class AndroidHistoryStorage { private HistoryStorage historyStorage; private Vector<String> messages = null; AndroidHistoryStorage(HistoryStorage storage) { historyStorage = storage; } public void addText(String text, boolean incoming, String from, long gmtTime) { jimm.modules.fs.JSR75FileSystem fs = getFile(); try { boolean exist = fs.exists(); OutputStream out = fs.openForAppendOutputStream(); try { if (!exist) { String header = "# history with " + historyStorage.getUniqueUserId() + "\n\n"; out.write(StringUtils.stringToByteArrayUtf8(header)); } String f = "[" + from + " " + Util.getLocalDateString(gmtTime, false) + "]\n" + text + "\n"; out.write(StringUtils.stringToByteArrayUtf8(f)); } finally { out.close(); fs.close(); } } catch (Exception ignored) { } fs.close(); } public int getHistorySize() { return 5; } public CachedRecord getRecord(int recNo) { return getLastRecord(getHistorySize() - recNo - 1); } private CachedRecord getLastRecord(int recNo) { jimm.modules.fs.JSR75FileSystem fs = getFile(); CachedRecord message = null; try { String last = toString(readLast(fs, 10 * 1024)); if (null == messages) messages = explodeMessages(last, getHistorySize()); message = parseMessage(messages.get(recNo)); if (recNo == messages.size() - 1) messages = null; } catch (Exception ignored) { } fs.close(); return message; } private CachedRecord parseMessage(String msg) { CachedRecord cachedRecord = new CachedRecord(); String header = msg.substring(1, msg.indexOf("]\n")); int loginTimeDelim = header.lastIndexOf(' ', header.lastIndexOf(' ') - 1); cachedRecord.from = header.substring(0, loginTimeDelim); cachedRecord.date = header.substring(loginTimeDelim + 1); cachedRecord.text = msg.substring(msg.indexOf("]\n") + 2); cachedRecord.type = 0; if (Jimm.getJimm().jimmModel.getProtocol(historyStorage.getContact()) .getNick().equals(cachedRecord.from)) { cachedRecord.type = 1; } return cachedRecord; } private jimm.modules.fs.JSR75FileSystem getFile() { return HomeDirectory.getFile(jimm.modules.fs.FileSystem.HISTORY + "/" + historyStorage.getUniqueUserId() + ".txt"); } public String getTextFile() { try { return getFile().exists() ? getFile().getAbsolutePath() : null; } catch (Exception e) { return null; } } private byte[] readLast(jimm.modules.fs.JSR75FileSystem fs, int read) throws Exception { InputStream in = fs.openInputStream(); try { int size = in.available(); read = Math.min(size, read); int offset = size - read; if (0 < offset) in.skip(offset); byte[] buffer = new byte[read]; int used = in.read(buffer); return (used < buffer.length) ? trim(buffer, used) : buffer; } finally { in.close(); } } private byte[] trim(byte[] array, int size) { byte[] out = new byte[size]; System.arraycopy(array, 0, out, 0, size); return out; } private String toString(byte[] in) { for (int i = 0; i < in.length; ++i) { if (in[i] == '[') break; in[i] = ' '; } return StringUtils.utf8beByteArrayToString(in, 0, in.length).trim(); } private Vector<String> explodeMessages(String str, int limit) { Vector<String> messages = new Vector<String>(); int messageEnd = str.length(); int cursor = messageEnd; while (0 < cursor) { int headerStart = str.lastIndexOf('[', cursor); if (isHeader(str, headerStart)) { messages.add(str.substring(headerStart, messageEnd)); messageEnd = headerStart - 1; if (messages.size() == limit) break; } cursor = headerStart - 1; } return messages; } private boolean isHeader(String str, int headerStart) { int headerEnd = str.indexOf("]", headerStart); if ((headerStart < 1) || (headerEnd < 2)) return false; Matcher matcher = headerPattern.matcher(str.substring(headerStart - 1, headerEnd + 2)); if (matcher.matches()) { char first = str.charAt(headerEnd + 2); return ('«' != first) && ( '»' != first); } return false; } private static final Pattern headerPattern = Pattern.compile("\n\\[[^\n]+ \\d{2}\\.\\d{2}\\.\\d{4} \\d{2}:\\d{2}\\]\n"); }