/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023, 2025 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.rms;
import java.io.*;
import java.util.*;
import malik.emulator.io.cloud.*;
import malik.emulator.io.vfs.*;
import malik.emulator.util.*;
public class RecordStore extends Object
{
private static final class DefaultFilterComparator extends Object implements RecordFilter, RecordComparator
{
public DefaultFilterComparator() {
}
public boolean matches(byte[] recordData) {
return true;
}
public int compare(byte[] recordData1, byte[] recordData2) {
return EQUIVALENT;
}
}
private static final char HEX_PREFIX = '$';
public static final int AUTHMODE_PRIVATE = 0;
public static final int AUTHMODE_ANY = 1;
public static final int STATE_ERROR = -1;
public static final int STATE_RESERV = 0;
public static final int STATE_OPENED = 1;
public static final int STATE_CLOSED = 2;
private static final int NAME_MAXIMUM_LENGTH = 32;
private static final long RMS_SIGNATURE = 0x6d6964702d726d73L;
private static final String RMS_DIR_NAME = "/rms";
private static final String RMS_DIR_PATH = RMS_DIR_NAME + "/";
private static final String RMS_EXTENSION = ".rms";
private static RecordStore[] OPENED;
private static final RecordFilter DEFAULT_FILTER;
private static final RecordComparator DEFAULT_COMPARATOR;
static final Object MONITOR;
static {
DefaultFilterComparator ref = new DefaultFilterComparator();
OPENED = new RecordStore[2];
DEFAULT_FILTER = ref;
DEFAULT_COMPARATOR = ref;
MONITOR = ref;
}
public static void closeAllRecordStores() {
synchronized(MONITOR)
{
for(int i = OPENED.length; i-- > 0; )
{
RecordStore store;
if((store = OPENED[i]) != null && store.openedCount != 0)
{
if(store.saveData())
{
store.openedCount = 0;
store.close();
continue;
}
System.out.println((new StringBuilder()).append("/!\\ RecordStore.closeAllRecordStores: не удалось сохранить хранилище записей ").append(store.name).append(".").toString());
}
}
}
}
public static void deleteRecordStore(String name) throws RecordStoreException {
int error;
checkName("deleteRecordStore", name);
error = 0;
synchronized(MONITOR)
{
label0:
{
int i;
if((i = indexOfRecordStore(name)) >= 0)
{
if(OPENED[i].openedCount != 0)
{
error = 1;
break label0;
}
OPENED[i] = null;
}
}
}
if(error == 1)
{
throw new RecordStoreException((new StringBuilder()).append("RecordStore.deleteRecordStore: невозможно удалить открытое хранилище записей ").append(name).append(".").toString());
}
try
{
CloudFileSystem.instance.deleteFile(toFileName(name));
}
catch(IOException e)
{
throw new RecordStoreNotFoundException((new StringBuilder()).append("RecordStore.deleteRecordStore: не удалось найти хранилище записей ").append(name).append(".").toString());
}
}
public static int getState(String name) {
int i;
RecordStore store;
return
name == null || (i = name.length()) < 1 || i > NAME_MAXIMUM_LENGTH ? STATE_ERROR :
(store = getRecordStore(name)) == null ? STATE_RESERV :
store.openedCount != 0 ? STATE_OPENED : STATE_CLOSED
;
}
public static String[] listRecordStores() {
int i;
int extlen = RMS_EXTENSION.length();
String[] result;
Vector list = new Vector(i = OPENED.length);
while(i-- > 0)
{
RecordStore store;
if((store = OPENED[i]) != null) list.addElement(store.name);
}
try
{
FileEnumeration e;
if((e = CloudFileSystem.instance.findFirst(RMS_DIR_PATH)) != null)
{
try
{
do
{
int len;
String n;
if(
!e.isDirectory() && (n = e.getName()) != null && n.regionMatches(true, len = n.length() - extlen, RMS_EXTENSION, 0, extlen) &&
isStoreName(n = n.substring(0, len)) && !list.contains(n = toStoreName(n))
) list.addElement(n);
} while(e.findNext());
}
finally
{
e.close();
}
}
}
catch(IOException e)
{
e.printRealStackTrace();
}
list.copyInto(result = new String[list.size()]);
return result;
}
public static RecordStore openRecordStore(String name, boolean createIfNecessary) throws RecordStoreException {
int error;
RecordStore result;
checkName("openRecordStore", name);
error = 0;
synchronized(MONITOR)
{
label0:
{
int i;
if((i = indexOfRecordStore(name)) >= 0)
{
if((i = (result = OPENED[i]).openedCount) == 0 && !result.loadData() && !createIfNecessary)
{
error = 1;
break label0;
}
result.openedCount = i + 1;
} else
{
if(!(result = new RecordStore(name)).loadData() && !createIfNecessary)
{
error = 2;
break label0;
}
register(result);
result.openedCount = 1;
}
}
}
switch(error)
{
case 1:
throw new RecordStoreException((new StringBuilder()).append("RecordStore.openRecordStore: не удалось загрузить хранилище записей ").append(name).append(".").toString());
case 2:
throw new RecordStoreNotFoundException((new StringBuilder()).append("RecordStore.openRecordStore: не удалось найти хранилище записей ").append(name).append(".").toString());
}
return result;
}
public static RecordStore openRecordStore(String name, boolean createIfNecessary, int authmode, boolean writable) throws RecordStoreException {
return openRecordStore(name, createIfNecessary);
}
public static RecordStore openRecordStore(String name, String vendorName, String suiteName) throws RecordStoreException {
return openRecordStore(name, false);
}
private static void checkName(String method, String name) {
int len;
if(name == null || (len = name.length()) < 1 || len > NAME_MAXIMUM_LENGTH)
{
throw new IllegalArgumentException((new StringBuilder()).append("RecordStore.").append(method).append(": недопустимое имя хранилища записей.").toString());
}
}
private static void register(RecordStore store) {
int i;
int len;
if((i = Array.findb(OPENED, (len = OPENED.length) - 1, null)) >= 0)
{
OPENED[i] = store;
return;
}
Array.copy(OPENED, 0, OPENED = new RecordStore[len << 1], 0, len);
OPENED[len] = store;
}
private static boolean isStoreName(String name) {
int len;
char[] chars;
name.getChars(0, len = name.length(), chars = new char[len + 1], 0);
for(int i = 0; i < len; )
{
char c;
char code;
if((c = chars[i++]) != HEX_PREFIX)
{
if(c == '_' || c >= '0' && c <= '9' || c >= 'a' && c <= 'z') continue;
return false;
}
code = 0;
for(int j = 4; j-- > 0; )
{
if((c = chars[i++]) >= '0' && c <= '9')
{
code = (char) ((code << 4) | (c - '0'));
continue;
}
if(c >= 'A' && c <= 'F')
{
code = (char) ((code << 4) | (c - ('A' - 0x0a)));
continue;
}
return false;
}
if((c = code) == '_' || c >= '0' && c <= '9' || c >= 'a' && c <= 'z') return false;
}
return true;
}
private static char getDigitRepresentation(int digit) {
if(digit >= 0x00 && digit < 0x0a) return (char) (digit + '0');
if(digit >= 0x0a && digit < 0x10) return (char) (digit + ('A' - 0x0a));
throw new ArrayIndexOutOfBoundsException(digit);
}
private static int indexOfRecordStore(String name) {
int i;
RecordStore store;
for(i = OPENED.length; i-- > 0; ) if((store = OPENED[i]) != null && name.equals(store.name)) return i;
return -1;
}
private static RecordStore getRecordStore(String name) {
int i;
RecordStore store;
for(i = OPENED.length; i-- > 0; ) if((store = OPENED[i]) != null && name.equals(store.name)) return store;
return null;
}
private static String toStoreName(String fileName) {
int length = 0;
char[] result = new char[NAME_MAXIMUM_LENGTH];
for(int len = fileName.length(), i = 0; i < len && length < NAME_MAXIMUM_LENGTH; )
{
char c;
if((c = fileName.charAt(i++)) == HEX_PREFIX)
{
int j = 0;
c = 0;
do
{
char d;
if(i >= len) break;
if((d = fileName.charAt(i++)) >= '0' && d <= '9')
{
c = (char) ((c << 4) | (d - '0'));
continue;
}
if(d >= 'A' && d <= 'F')
{
c = (char) ((c << 4) | (d - ('A' - 0x0a)));
continue;
}
break;
} while(++j < 4);
}
result[length++] = c;
}
return new String(result, 0, length);
}
private static String toFileName(String name) {
int length = 0;
char[] result = new char[5 * NAME_MAXIMUM_LENGTH];
for(int len = name.length(), i = 0; i < len; )
{
char c;
if((c = name.charAt(i++)) == '_' || c >= '0' && c <= '9' || c >= 'a' && c <= 'z')
{
result[length++] = c;
continue;
}
result[length++] = HEX_PREFIX;
result[length++] = getDigitRepresentation((c >> 0x0c) & 0x0f);
result[length++] = getDigitRepresentation((c >> 0x08) & 0x0f);
result[length++] = getDigitRepresentation((c >> 0x04) & 0x0f);
result[length++] = getDigitRepresentation(c & 0x0f);
}
return (new StringBuilder()).append(RMS_DIR_PATH).append(result, 0, length).append(RMS_EXTENSION).toString();
}
private final class Enumerator extends Object implements RecordListener, RecordEnumeration
{
private boolean nowCreated;
private boolean autoRebuild;
private int current;
private int count;
private Record[] records;
private final RecordComparator comparator;
private final RecordFilter filter;
private final Object monitor;
public Enumerator(RecordFilter filter, RecordComparator comparator, boolean autoRebuild) {
this.nowCreated = true;
this.autoRebuild = autoRebuild;
this.comparator = comparator;
this.filter = filter;
this.monitor = new Object();
rebuild();
if(autoRebuild) (RecordStore.this).addRecordListener(this);
}
public void recordAdded(RecordStore store, int recordID) {
if(store == RecordStore.this) rebuild();
}
public void recordChanged(RecordStore store, int recordID) {
if(store == RecordStore.this) rebuild();
}
public void recordDeleted(RecordStore store, int recordID) {
if(store == RecordStore.this) rebuild();
}
public void destroy() {
}
public void rebuild() {
boolean opened;
int sourceCount;
int rebuildedCount;
Record[] sourceRecs;
Record[] rebuildedRecs;
RecordComparator comparator = this.comparator;
RecordFilter filter = this.filter;
RecordStore store = RecordStore.this;
synchronized(RecordStore.MONITOR)
{
if(opened = store.openedCount != 0)
{
sourceCount = store.count;
sourceRecs = store.records;
} else
{
sourceCount = 0;
sourceRecs = null;
}
}
if(sourceRecs == null || !opened) return;
rebuildedCount = 0;
rebuildedRecs = new Record[sourceCount];
try
{
for(int i = 0; i < sourceCount; i++)
{
Record rec;
if((rec = sourceRecs[i]) != null && filter.matches(rec.getData())) rebuildedRecs[rebuildedCount++] = rec;
}
for(int lim = rebuildedCount - 1, i = 0; i < lim; i++)
{
Record rec1 = rebuildedRecs[i];
for(int j = i + 1; j < rebuildedCount; j++)
{
Record rec2 = rebuildedRecs[j];
if(comparator.compare(rec2.getData(), rec1.getData()) < 0)
{
rebuildedRecs[i] = rec2;
rebuildedRecs[j] = rec1;
rec1 = rec2;
}
}
}
}
catch(RuntimeException e)
{
e.printRealStackTrace();
return;
}
synchronized(monitor)
{
nowCreated = true;
count = rebuildedCount;
records = rebuildedRecs;
}
}
public void reset() {
synchronized(monitor)
{
nowCreated = true;
}
}
public void keepUpdated(boolean autoRebuild) {
synchronized(monitor)
{
if(this.autoRebuild != autoRebuild)
{
if(this.autoRebuild = autoRebuild)
{
(RecordStore.this).addRecordListener(this);
} else
{
(RecordStore.this).removeRecordListener(this);
}
}
}
if(autoRebuild) rebuild();
}
public boolean isKeptUpdated() {
return autoRebuild;
}
public boolean hasNextElement() {
boolean result;
synchronized(monitor)
{
result = nowCreated ? count > 0 : current < count - 1;
}
return result;
}
public boolean hasPreviousElement() {
boolean result;
synchronized(monitor)
{
result = nowCreated ? count > 0 : current > 0;
}
return result;
}
public int numRecords() {
return count;
}
public int nextRecordId() throws InvalidRecordIDException {
int error = 0;
int result;
synchronized(monitor)
{
label0:
{
int index;
if((index = toNextRecord()) < 0)
{
error = 1;
result = 0;
break label0;
}
result = records[index].getID();
}
}
if(error == 1)
{
throw new InvalidRecordIDException("RecordEnumeration.nextRecordId: в перечислении больше не осталось записей.");
}
return result;
}
public int previousRecordId() throws InvalidRecordIDException {
int error = 0;
int result;
synchronized(monitor)
{
label0:
{
int index;
if((index = toPrevRecord()) < 0)
{
error = 1;
result = 0;
break label0;
}
result = records[index].getID();
}
}
if(error == 1)
{
throw new InvalidRecordIDException("RecordEnumeration.previousRecordId: в перечислении больше не осталось записей.");
}
return result;
}
public byte[] nextRecord() throws RecordStoreException {
int error = 0;
byte[] result;
RecordStore store;
synchronized(monitor)
{
label0:
{
int len;
int index;
if((store = RecordStore.this).openedCount == 0)
{
error = 1;
result = null;
break label0;
}
if((index = toNextRecord()) < 0)
{
error = 2;
result = null;
break label0;
}
Array.copy(result = records[index].getData(), 0, result = new byte[len = result.length], 0, len);
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordEnumeration.nextRecord: хранилище записей ").append(store.name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException("RecordEnumeration.nextRecord: в перечислении больше не осталось записей.");
}
return result;
}
public byte[] previousRecord() throws RecordStoreException {
int error = 0;
byte[] result;
RecordStore store;
synchronized(monitor)
{
label0:
{
int len;
int index;
if((store = RecordStore.this).openedCount == 0)
{
error = 1;
result = null;
break label0;
}
if((index = toPrevRecord()) < 0)
{
error = 2;
result = null;
break label0;
}
Array.copy(result = records[index].getData(), 0, result = new byte[len = result.length], 0, len);
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordEnumeration.previousRecord: хранилище записей ").append(store.name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException("RecordEnumeration.previousRecord: в перечислении больше не осталось записей.");
}
return result;
}
private int toNextRecord() {
int cur;
if(nowCreated)
{
if(count <= 0) return -1;
nowCreated = false;
return current = 0;
}
return (cur = current) >= count - 1 ? -1 : (current = cur + 1);
}
private int toPrevRecord() {
int cur;
if(nowCreated)
{
int cnt;
if((cnt = count) <= 0) return -1;
nowCreated = false;
return current = cnt - 1;
}
return (cur = current) <= 0 ? -1 : (current = cur - 1);
}
}
int openedCount;
private int version;
private int nextID;
int count;
private long lastModified;
Record[] records;
private RecordListener[] listeners;
final String name;
private RecordStore(String name) {
this.name = name;
}
public void addRecordListener(RecordListener listener) {
if(listener == null) return;
synchronized(MONITOR)
{
int len;
RecordListener[] listeners;
if((listeners = this.listeners) == null) listeners = this.listeners = new RecordListener[3];
if(Array.findf(listeners, 0, listener) >= (len = listeners.length))
{
int index;
if((index = Array.findf(listeners, 0, null)) >= len)
{
Array.copy(listeners, 0, listeners = new RecordListener[(len << 1) + 1], 0, len);
this.listeners = listeners;
}
listeners[index] = listener;
}
}
}
public void removeRecordListener(RecordListener listener) {
if(listener == null) return;
synchronized(MONITOR)
{
int index;
RecordListener[] listeners;
if((listeners = this.listeners) != null && (index = Array.findf(listeners, 0, listener)) < listeners.length) listeners[index] = null;
}
}
public void closeRecordStore() throws RecordStoreException {
int error = 0;
synchronized(MONITOR)
{
label0:
{
int i;
if((i = openedCount) == 0)
{
error = 1;
break label0;
}
if((openedCount = i - 1) == 0)
{
if(!saveData())
{
error = 2;
break label0;
}
close();
}
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.closeRecordStore: невозможно закрыть уже закрытое хранилище записей ").append(name).append(".").toString());
case 2:
throw new RecordStoreException((new StringBuilder()).append("RecordStore.closeRecordStore: не удалось сохранить хранилище записей ").append(name).append(".").toString());
}
}
public void deleteRecord(int recordID) throws RecordStoreException {
int error = 0;
synchronized(MONITOR)
{
label0:
{
int len;
int index;
Record[] recs;
if(openedCount == 0)
{
error = 1;
break label0;
}
if((index = indexOfRecord(recordID)) < 0)
{
error = 2;
break label0;
}
recs = records;
if((len = count - 1) > index) Array.copy(recs, index + 1, recs, index, len - index);
recs[count = len] = null;
version++;
lastModified = System.currentTimeMillis();
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.deleteRecord: хранилище записей ").append(name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException((new StringBuilder()).append("RecordStore.deleteRecord: неизвестный идентификатор записи (").append(recordID).append(").").toString());
}
notifyListenersDeleted(recordID);
}
public void setMode(int authmode, boolean writable) throws RecordStoreException {
if(authmode != AUTHMODE_ANY && authmode != AUTHMODE_PRIVATE)
{
throw new IllegalArgumentException("RecordStore.setMode: аргумент authmode имеет недопустимое значение.");
}
}
public void setRecord(int recordID, byte[] src, int offset, int length) throws RecordStoreException {
int error;
if(src != null) Array.checkBound("RecordStore.setRecord", src.length, offset, length);
error = 0;
synchronized(MONITOR)
{
label0:
{
int index;
if(openedCount == 0)
{
error = 1;
break label0;
}
if((index = indexOfRecord(recordID)) < 0)
{
error = 2;
break label0;
}
if(src != null)
{
Array.copy(src, offset, src = new byte[length], 0, length);
} else
{
src = new byte[0];
}
records[index].setData(src);
version++;
lastModified = System.currentTimeMillis();
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.setRecord: хранилище записей ").append(name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException((new StringBuilder()).append("RecordStore.setRecord: неизвестный идентификатор записи (").append(recordID).append(").").toString());
}
notifyListenersChanged(recordID);
}
public int addRecord(byte[] src, int offset, int length) throws RecordStoreException {
int error;
int result;
if(src != null) Array.checkBound("RecordStore.addRecord", src.length, offset, length);
error = 0;
synchronized(MONITOR)
{
label0:
{
int len;
Record[] recs;
if(openedCount == 0)
{
error = 1;
result = 0;
break label0;
}
if((recs = records) == null || recs.length <= 0) recs = records = new Record[3];
if((len = count) == recs.length) Array.copy(recs, 0, recs = records = new Record[(len << 1) + 1], 0, len);
if(src != null)
{
Array.copy(src, offset, src = new byte[length], 0, length);
} else
{
src = new byte[0];
}
recs[len] = new Record(result = nextID++, src);
count = len + 1;
version++;
lastModified = System.currentTimeMillis();
}
}
if(error == 1)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.addRecord: хранилище записей ").append(name).append(" не открыто.").toString());
}
notifyListenersAdded(result);
return result;
}
public int getRecord(int recordID, byte[] dst, int offset) throws RecordStoreException {
int error;
int result;
if(dst == null)
{
throw new NullPointerException("RecordStore.getRecord: аргумент dst равен нулевой ссылке.");
}
error = 0;
synchronized(MONITOR)
{
label0:
{
int index;
byte[] data;
if(openedCount == 0)
{
error = 1;
result = 0;
break label0;
}
if((index = indexOfRecord(recordID)) < 0)
{
error = 2;
result = 0;
break label0;
}
if(!Array.isBoundValid(dst.length, offset, result = (data = records[index].getData()).length))
{
error = 3;
result = 0;
break label0;
}
Array.copy(data, 0, dst, offset, result);
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getRecord: хранилище записей ").append(name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException((new StringBuilder()).append("RecordStore.getRecord: неизвестный идентификатор записи (").append(recordID).append(").").toString());
case 3:
throw new ArrayIndexOutOfBoundsException("RecordStore.getRecord: индекс выходит из диапазона.");
}
return result;
}
public int getRecordSize(int recordID) throws RecordStoreException {
int error = 0;
int result;
synchronized(MONITOR)
{
label0:
{
int index;
if(openedCount == 0)
{
error = 1;
result = 0;
break label0;
}
if((index = indexOfRecord(recordID)) < 0)
{
error = 2;
result = 0;
break label0;
}
result = records[index].getSize();
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getRecordSize: хранилище записей ").append(name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException((new StringBuilder()).append("RecordStore.getRecordSize: неизвестный идентификатор записи (").append(recordID).append(").").toString());
}
return result;
}
public int getNextRecordID() throws RecordStoreException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getNextRecordID: хранилище записей ").append(name).append(" не открыто.").toString());
}
return nextID;
}
public int getNumRecords() throws RecordStoreNotOpenException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getNumRecords: хранилище записей ").append(name).append(" не открыто.").toString());
}
return count;
}
public int getVersion() throws RecordStoreNotOpenException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getVersion: хранилище записей ").append(name).append(" не открыто.").toString());
}
return version;
}
public int getSize() throws RecordStoreNotOpenException {
int error = 0;
int result;
synchronized(MONITOR)
{
label0:
{
Record[] recs;
if(openedCount == 0)
{
error = 1;
result = 0;
break label0;
}
result = 0x20;
recs = records;
for(int i = count; i-- > 0; )
{
result += recs[i].getSize() + 0x08;
result += -result & 0x03;
}
}
}
if(error == 1)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getSize: хранилище записей ").append(name).append(" не открыто.").toString());
}
return result;
}
public int getSizeAvailable() throws RecordStoreNotOpenException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getSizeAvailable: хранилище записей ").append(name).append(" не открыто.").toString());
}
return Memory.getFree();
}
public long getLastModified() throws RecordStoreNotOpenException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getLastModified: хранилище записей ").append(name).append(" не открыто.").toString());
}
return lastModified;
}
public byte[] getRecord(int recordID) throws RecordStoreException {
int error = 0;
byte[] result;
synchronized(MONITOR)
{
label0:
{
int len;
int index;
byte[] data;
if(openedCount == 0)
{
error = 1;
result = null;
break label0;
}
if((index = indexOfRecord(recordID)) < 0)
{
error = 2;
result = null;
break label0;
}
Array.copy(data = records[index].getData(), 0, result = new byte[len = data.length], 0, len);
}
}
switch(error)
{
case 1:
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.getRecord: хранилище записей ").append(name).append(" не открыто.").toString());
case 2:
throw new InvalidRecordIDException((new StringBuilder()).append("RecordStore.getRecord: неизвестный идентификатор записи (").append(recordID).append(").").toString());
}
return result;
}
public String getName() throws RecordStoreNotOpenException {
return name;
}
public RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean autoRebuild) throws RecordStoreNotOpenException {
if(openedCount == 0)
{
throw new RecordStoreNotOpenException((new StringBuilder()).append("RecordStore.enumerateRecords: хранилище записей ").append(name).append(" не открыто.").toString());
}
return this.new Enumerator(filter == null ? DEFAULT_FILTER : filter, comparator == null ? DEFAULT_COMPARATOR : comparator, autoRebuild);
}
private void notifyListenersAdded(int recordID) {
RecordListener[] listeners;
for(int i = (listeners = this.listeners) == null ? 0 : listeners.length; i-- > 0; )
{
RecordListener listener;
if((listener = listeners[i]) != null)
{
try
{
listener.recordAdded(this, recordID);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
}
private void notifyListenersChanged(int recordID) {
RecordListener[] listeners;
for(int i = (listeners = this.listeners) == null ? 0 : listeners.length; i-- > 0; )
{
RecordListener listener;
if((listener = listeners[i]) != null)
{
try
{
listener.recordChanged(this, recordID);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
}
private void notifyListenersDeleted(int recordID) {
RecordListener[] listeners;
for(int i = (listeners = this.listeners) == null ? 0 : listeners.length; i-- > 0; )
{
RecordListener listener;
if((listener = listeners[i]) != null)
{
try
{
listener.recordDeleted(this, recordID);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
}
}
private void close() {
count = 0;
records = null;
listeners = null;
System.out.println((new StringBuilder()).append("RecordStore: внесены изменения в запись ").append(name).append(".").toString());
}
private boolean saveData() {
boolean result;
HandleOutputStream file;
try
{
try
{
CloudFileSystem.instance.readAttributes(RMS_DIR_NAME, null);
}
catch(IOException e)
{
CloudFileSystem.instance.createDirectory(RMS_DIR_NAME);
}
}
catch(IOException e)
{
}
if((file = new FileOutputStream(toFileName(name))).hasOpenError()) return false;
try
{
try
{
int len = count;
Record[] recs = records;
DataOutputStream stream;
(stream = new DataOutputStream(file)).writeLong(RMS_SIGNATURE);
stream.writeInt(len);
stream.writeInt(version);
stream.writeLong(lastModified);
stream.writeInt(nextID);
stream.writeInt(0);
for(int i = 0; i < len; i++)
{
int size;
Record rec = recs[i];
stream.writeInt(rec.getID());
stream.writeInt(size = rec.getSize());
stream.write(rec.getData());
switch(size & 3)
{
case 1:
stream.writeByte(0);
/* fall through */
case 2:
stream.writeByte(0);
/* fall through */
case 3:
stream.writeByte(0);
/* fall through */
default:
break;
}
}
}
finally
{
file.close();
}
result = true;
}
catch(IOException e)
{
e.printRealStackTrace();
result = false;
}
return result;
}
private boolean loadData() {
boolean result;
HandleInputStream file;
if((file = new FileInputStream(toFileName(name))).hasOpenError())
{
version = 1;
nextID = 1;
count = 0;
lastModified = System.currentTimeMillis();
records = null;
return false;
}
try
{
try
{
DataInputStream stream;
if((stream = new DataInputStream(file)).readLong() != RMS_SIGNATURE)
{
version = 1;
nextID = 1;
count = 0;
lastModified = System.currentTimeMillis();
records = null;
result = false;
} else
{
int len;
Record[] recs;
count = len = stream.readInt();
version = stream.readInt();
lastModified = stream.readLong();
nextID = stream.readInt();
records = recs = new Record[len];
stream.skipBytes(4);
for(int i = 0; i < len; i++)
{
int id = stream.readInt();
int size = stream.readInt();
byte[] data;
stream.read(data = new byte[size]);
if((size &= 3) != 0) stream.skipBytes(4 - size);
recs[i] = new Record(id, data);
}
result = true;
}
}
finally
{
file.close();
}
}
catch(IOException e)
{
e.printRealStackTrace();
result = false;
}
return result;
}
private int indexOfRecord(int recordID) {
Record[] recs = records;
for(int i = count; i-- > 0; ) if(recs[i].getID() == recordID) return i;
return -1;
}
}
final class Record extends Object
{
private final int id;
private byte[] data;
public Record(int id, byte[] data) {
this.id = id;
this.data = data;
}
public void setData(byte[] data) {
this.data = data;
}
public int getID() {
return id;
}
public int getSize() {
return data.length;
}
public byte[] getData() {
return data;
}
}