package javax.microedition.rms;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import com.buglabs.bug.module.gps.Activator;
public class RecordStore {
public static final String AUTHMODE_ANY = "AUTHMODE_ANY";
private static final String PID_PREFIX = "RECORDSTORE_";
private static final String KEYSTORE_KEY = "KEYSTORE_KEY";
private String name;
private Dictionary props;
private int recordIndex = 0;
protected RecordStore(String name, Dictionary props) {
this.name = name;
this.props = props;
}
public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) throws RecordStoreException {
ConfigurationAdmin ca = getConfigurationAdmin(Activator.getContext());
if (ca == null) {
throw new RecordStoreException("Unable to access internal persistent store: ConfigurationAdmin.");
}
try {
Configuration c= ca.getConfiguration(createPid(recordStoreName));
//Will create an empty Dictionary if does not yet exist.
c.update();
if (c.getProperties().get(KEYSTORE_KEY) == null && !createIfNecessary) {
throw new RecordStoreException("Record store " + recordStoreName + " does not exist.");
}
Dictionary keystore = (Dictionary) c.getProperties().get(KEYSTORE_KEY);
if (keystore == null) {
keystore = new Hashtable();
c.getProperties().put(KEYSTORE_KEY, keystore);
}
return new RecordStore(recordStoreName, keystore);
} catch (IOException e) {
throw new RecordStoreException("Unable to access internal persistent store: ConfigurationAdmin.", e);
}
}
public int addRecord(byte[] data, int offset, int numBytes) throws RecordStoreFullException {
props.put(new Integer(recordIndex), new ByteArray(data));
recordIndex ++;
return recordIndex - 1;
}
public static void deleteRecordStore(String recordStoreName) throws RecordStoreNotFoundException {
ConfigurationAdmin ca = getConfigurationAdmin(Activator.getContext());
if (ca == null) {
throw new RecordStoreNotFoundException("Unable to access internal persistent store: ConfigurationAdmin.");
}
try {
Configuration c = ca.getConfiguration(createPid(recordStoreName));
if (c.getProperties() != null) {
c.delete();
}
} catch (IOException e) {
throw new RecordStoreNotFoundException(e.getMessage(), e);
}
}
public static String[] listRecordStores() throws IOException {
ConfigurationAdmin ca = getConfigurationAdmin(Activator.getContext());
if (ca == null) {
throw new IOException("Unable to access internal persistent store: ConfigurationAdmin.");
}
List stores = new ArrayList();
try {
Configuration[] configurations = ca.listConfigurations(null);
for (int i = 0; i < configurations.length; ++i) {
if (configurations[i].getPid().startsWith(PID_PREFIX)) {
stores.add(configurations[i].getPid().substring(PID_PREFIX.length()));
}
}
} catch (InvalidSyntaxException e) {
throw new IOException(e.getMessage());
}
return (String []) stores.toArray(new String[stores.size()]);
}
public void setMode(String authmodeAny, boolean b) {
//TODO implement
//this is unimplemented as it doesn't seem to be used by openlapi.
}
public byte[] getRecord(int iD) throws RecordStoreException {
ByteArray ba = (ByteArray) props.get(new Integer(iD));
if (ba == null) {
throw new RecordStoreException("Record ID " + iD + " does not exist.");
}
return ba.getBytes();
}
public void deleteRecord(int iD) throws RecordStoreException {
if (props.get(new Integer(iD)) == null) {
throw new RecordStoreException("Record ID " + iD + " does not exist.");
}
}
public RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated) {
if (filter != null || comparator != null) {
throw new RuntimeException("RMS filter and sort features unimplemented.");
}
return new RecordEnumerationImpl(props);
}
public String getName() {
return name;
}
public int getNumRecords() throws RecordStoreException {
return props.size();
}
public void setRecord(int recordId, byte[] data, int i, int length) throws RecordStoreException {
//TODO handle length, index. openlapi always seems to store full byte arrays.
props.put(new Integer(recordId), new ByteArray(data));
}
private static ConfigurationAdmin getConfigurationAdmin(BundleContext c) {
ServiceReference sr = c.getServiceReference(ConfigurationAdmin.class.getName());
if (sr != null) {
return (ConfigurationAdmin) c.getService(sr);
}
return null;
}
private static String createPid(String recordStoreName) {
return PID_PREFIX + recordStoreName;
}
/**
* Stores byte arrays for RMS records.
* @author kgilmer
*
*/
private class ByteArray {
private final byte[] bytes;
public ByteArray(byte[] data) {
this.bytes = data;
}
public byte[] getBytes() {
return bytes;
}
}
private class RecordEnumerationImpl implements RecordEnumeration {
private final Enumeration keys;
public RecordEnumerationImpl(Dictionary properties) {
keys = properties.keys();
}
public boolean hasNextElement() {
return keys.hasMoreElements();
}
public int nextRecordId() {
return ((Integer)keys.nextElement()).intValue();
}
}
}