001: /* Copyright 2005-2006 David N. Welton <davidw@dedasys.com>
002: * Wolfgang S. Kechel - wolfgang.kechel@data2c.com
003:
004: Licensed under the Apache License, Version 2.0 (the "License");
005: you may not use this file except in compliance with the License.
006: You may obtain a copy of the License at
007:
008: http://www.apache.org/licenses/LICENSE-2.0
009:
010: Unless required by applicable law or agreed to in writing, software
011: distributed under the License is distributed on an "AS IS" BASIS,
012: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: See the License for the specific language governing permissions and
014: limitations under the License.
015: */
016:
017: package org.hecl.rms;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.DataInputStream;
022: import java.io.DataOutputStream;
023: import java.io.IOException;
024: import java.util.Hashtable;
025: import java.util.Vector;
026:
027: import org.hecl.HeclException;
028: import org.hecl.Interp;
029: import org.hecl.IntThing;
030: import org.hecl.ListThing;
031: import org.hecl.Operator;
032: import org.hecl.RealThing;
033: import org.hecl.StringThing;
034: import org.hecl.Thing;
035:
036: import javax.microedition.rms.RecordStore;
037: import javax.microedition.rms.RecordEnumeration;
038:
039: /**
040: * The <code>RMSCmd</code> class implements the record store related commands.
041: *
042: * @author <a href="mailto:davidw@dedasys.com">David N. Welton</a>
043: * @author <a href="mailto:wolfgang.kechel@data2c.com.com">Wolfgang S. Kechel</a>
044: * @version 1.1
045: */
046: public class RMSCmd extends Operator {
047: public static final int RMS_LIST = 1;
048: public static final int RMS_CREATE = 2;
049: public static final int RMS_GET = 3;
050: public static final int RMS_SET = 4;
051: public static final int RMS_SIZE = 5;
052: public static final int RMS_SIZEAVAIL = 6;
053: public static final int RMS_DELETE = 7;
054: public static final int RMS_ADD = 8;
055: public static final int RMS_HSET = 9;
056: public static final int RMS_HGET = 10;
057: public static final int RMS_HEXISTS = 11;
058: public static final int RMS_HKEYS = 12;
059: public static final int RMS_HDEL = 13;
060: //#if midp >= 2.0
061: public static final int RMS_SETMODE = 14;
062:
063: //#endif
064:
065: protected RMSCmd(int cmdcode, int minargs, int maxargs) {
066: super (cmdcode, minargs, maxargs);
067: }
068:
069: protected static void closeRS(RecordStore rs) throws HeclException {
070: if (rs != null) {
071: try {
072: rs.closeRecordStore();
073: } catch (Exception e) {
074: throw new HeclException("Can't close recordstore.");
075: }
076: }
077: }
078:
079: public Thing operate(int cmd, Interp interp, Thing[] argv)
080: throws HeclException {
081: RecordStore rs = null;
082: byte[] data = null;
083: String name = argv.length > 1 ? argv[1].toString() : null;
084: int recordid = 1;
085:
086: switch (cmd) {
087: case RMS_LIST:
088: ;
089: {
090: Vector v = new Vector();
091: if (name == null) {
092: String[] names = RecordStore.listRecordStores();
093: if (names != null) {
094: for (int i = 0; i < names.length; i++) {
095: v.addElement(new Thing(names[i]));
096: }
097: }
098: } else {
099: int[] res = getRecordIds(name);
100: for (int i = 0; i < res.length; ++i)
101: v.addElement(IntThing.create(res[i]));
102: }
103: return ListThing.create(v);
104: }
105:
106: case RMS_CREATE:
107: ;
108: {
109: //#if midp < 2.0
110:
111: // name already extracted
112:
113: //#else
114: // [options] name
115: name = null;
116: int authmode = RecordStore.AUTHMODE_PRIVATE;
117: boolean writeflag = false;
118: boolean argend = false;
119:
120: for (int i = 1; i < argv.length; ++i) {
121: String s = argv[1].toString();
122: if (!argend && s.equals("--")) {
123: argend = true;
124: continue;
125: }
126: if (!argend && s.startsWith("-")) {
127: // option
128: if (s.equals("-any"))
129: authmode = RecordStore.AUTHMODE_ANY;
130: if (s.equals("-private"))
131: authmode = RecordStore.AUTHMODE_PRIVATE;
132: else if (s.equals("-writable"))
133: writeflag = true;
134: else
135: throw new HeclException("unknown option '"
136: + s + "'");
137: } else {
138: name = s;
139: }
140: }
141: if (name == null)
142: throw new HeclException("name required");
143: //#endif
144: try {
145: rs = RecordStore.openRecordStore(name, true
146: //#ifdef MIDP20
147: , authmode, writeflag
148: //#endif
149: );
150: } catch (Exception e) {
151: /* FIXME - we ought to do something a little bit more clever here. */
152: throw new HeclException(e.toString());
153: } finally {
154: closeRS(rs);
155: }
156: return new Thing(name);
157: }
158:
159: case RMS_GET:
160: // rs_get name [recordid]
161: if (argv.length > 2) {
162: recordid = IntThing.get(argv[2]);
163: }
164: try {
165: rs = RecordStore.openRecordStore(name, false);
166: data = rs.getRecord(recordid);
167: } catch (Exception e) {
168: /* FIXME - we ought to do something a little bit more clever here. */
169: throw new HeclException(e.toString());
170: } finally {
171: closeRS(rs);
172: }
173: return new Thing(new String(data));
174:
175: case RMS_SET:
176: // rs_put name [recordid=1] data
177: //System.err.println("argv.length="+argv.length);
178:
179: if (argv.length > 3) {
180: recordid = IntThing.get(argv[2]);
181: data = argv[3].toString().getBytes();
182: } else {
183: data = argv[2].toString().getBytes();
184: }
185:
186: try {
187: rs = RecordStore.openRecordStore(name, true);
188: //rs.addRecord(data, 0, data.length);
189: rs.setRecord(recordid, data, 0, data.length);
190: } catch (Exception e) {
191: throw new HeclException(e.toString());
192: } finally {
193: closeRS(rs);
194: }
195: return IntThing.create(data.length);
196:
197: case RMS_ADD:
198: // add data
199: try {
200: rs = RecordStore.openRecordStore(name, false);
201: data = argv[2].toString().getBytes();
202: recordid = rs.addRecord(data, 0, data.length);
203: } catch (Exception e) {
204: throw new HeclException("Can't add record: "
205: + e.getMessage());
206: } finally {
207: closeRS(rs);
208: }
209: return IntThing.create(recordid);
210:
211: case RMS_SIZE:
212: case RMS_SIZEAVAIL:
213: // size recordid
214: // we reuse the recordid var!
215: try {
216: rs = RecordStore.openRecordStore(name, true);
217: recordid = cmd == RMS_SIZE ? rs.getSize() : rs
218: .getSizeAvailable();
219: } catch (Exception e) {
220: throw new HeclException(e.toString());
221: } finally {
222: closeRS(rs);
223: }
224: return IntThing.create(recordid);
225:
226: case RMS_DELETE:
227: recordid = -1;
228: if (argv.length > 2) {
229: recordid = IntThing.get(argv[2]);
230: }
231: if (recordid < 0) {
232: try {
233: RecordStore.deleteRecordStore(name);
234: } catch (Exception e) {
235: throw new HeclException(
236: "Can't delete recordstore '" + name + "': "
237: + e.getMessage());
238: }
239: break;
240: }
241: try {
242: rs = RecordStore.openRecordStore(name, false);
243: rs.deleteRecord(recordid);
244: } catch (Exception e) {
245: throw new HeclException("Can't delete recordstore '"
246: + name + "[" + recordid + "]': "
247: + e.getMessage());
248: } finally {
249: closeRS(rs);
250: }
251: break;
252:
253: case RMS_HSET:
254: // rs_hset name key value
255: data = argv[3].toString().getBytes();
256: try {
257: rs = RecordStore.openRecordStore(name, true);
258: //rs.addRecord(data, 0, data.length);
259: String key = argv[2].toString();
260: Object[] v = recordOf(rs, key);
261: recordid = ((Integer) v[0]).intValue();
262: data = toData(key, argv[3].toString());
263: if (recordid < 0)
264: rs.addRecord(data, 0, data.length);
265: else
266: rs.setRecord(recordid, data, 0, data.length);
267: recordid = data.length;
268: data = null;
269: } catch (Exception e) {
270: throw new HeclException(e.toString());
271: } finally {
272: closeRS(rs);
273: }
274: return IntThing.create(recordid);
275:
276: case RMS_HGET:
277: // hget name key
278: ; // trick emacs indentation
279: {
280: Object[] v = null;
281:
282: try {
283: rs = RecordStore.openRecordStore(name, true);
284: v = recordOf(rs, argv[2].toString());
285: recordid = ((Integer) v[0]).intValue();
286: } catch (Exception e) {
287: throw new HeclException(e.toString());
288: } finally {
289: closeRS(rs);
290: }
291: return new Thing(
292: recordid >= 0 && v[1] != null ? (String) v[1]
293: : "");
294: }
295:
296: case RMS_HEXISTS:
297: // hget name key
298: try {
299: rs = RecordStore.openRecordStore(name, true);
300: Object[] v = recordOf(rs, argv[2].toString());
301: recordid = ((Integer) v[0]).intValue();
302: } catch (Exception e) {
303: throw new HeclException(e.toString());
304: } finally {
305: closeRS(rs);
306: }
307: return IntThing.create(recordid >= 0 ? 1 : 0);
308:
309: case RMS_HKEYS:
310: ;
311: {
312: Vector v = null;
313:
314: try {
315: rs = RecordStore.openRecordStore(name, true);
316: v = hkeys(rs);
317: } catch (Exception e) {
318: throw new HeclException(e.toString());
319: } finally {
320: closeRS(rs);
321: }
322: if (v == null)
323: v = new Vector();
324:
325: int n = v.size();
326: for (int i = 0; i < n; ++i)
327: v.setElementAt(new Thing((String) v.elementAt(i)),
328: i);
329: return ListThing.create(v);
330: }
331:
332: case RMS_HDEL:
333: try {
334: rs = RecordStore.openRecordStore(name, true);
335: Object[] v = recordOf(rs, argv[2].toString());
336: recordid = ((Integer) v[0]).intValue();
337: if (recordid >= 0)
338: rs.deleteRecord(recordid);
339: } catch (Exception e) {
340: throw new HeclException(e.toString());
341: } finally {
342: closeRS(rs);
343: }
344: break;
345:
346: //#if midp >= 2.0
347: case RMS_SETMODE:
348: try {
349: int authmode = "any".equals(argv[2].toString()) ? RecordStore.AUTHMODE_ANY
350: : RecordStore.AUTHMODE_PRIVATE;
351: boolean writeflag = Thing.isTrue(argv[3]);
352: rs = RecordStore.openRecordStore(name, true);
353: rs.setMode(authmode, writeflag);
354: } catch (Exception e) {
355: throw new HeclException(e.toString());
356: } finally {
357: closeRS(rs);
358: }
359: break;
360: //#endif
361:
362: default:
363: throw new HeclException("Unknown rms command '"
364: + argv[0].toString() + "' with code '" + cmd + "'.");
365: }
366: return null;
367: }
368:
369: public static int[] getRecordIds(String name) throws HeclException {
370: int count = 0;
371: int[] res = new int[0];
372: RecordStore rs = null;
373: try {
374: rs = RecordStore.openRecordStore(name, false);
375: synchronized (rs) {
376: RecordEnumeration records = rs.enumerateRecords(null,
377: null, false);
378: while (records.hasNextElement()) {
379: records.nextRecordId();
380: ++count;
381: }
382: records.reset();
383: res = new int[count];
384: int i = 0;
385: while (records.hasNextElement()) {
386: res[i++] = records.nextRecordId();
387: }
388: records.destroy();
389: }
390: } catch (Exception e) {
391: /* FIXME - we ought to do something a little bit more clever here. */
392: throw new HeclException(e.toString());
393: } finally {
394: closeRS(rs);
395: }
396: return res;
397: }
398:
399: private static byte[] toData(String key, String value)
400: throws Exception {
401: ByteArrayOutputStream bos = null;
402: DataOutputStream dos = null;
403: byte[] data = null;
404:
405: try {
406: bos = new ByteArrayOutputStream();
407: dos = new DataOutputStream(bos);
408: dos.writeUTF(key);
409: dos.writeUTF(value);
410: data = bos.toByteArray();
411: dos.close();
412: bos.close();
413: } catch (Exception e) {
414: throw new HeclException("Can't create data: "
415: + e.getMessage());
416: }
417: return data;
418: }
419:
420: /*
421: Convert all rms records into a hashtable
422: private static Hashtable asTable(RecordStore rs) throws Exception {
423: Hashtable t = new Hashtable();
424:
425: RecordEnumeration enumeration = rs.enumerateRecords(null, null, false);
426: for (int i = 0; i < enumeration.numRecords(); i++) {
427: int tmpid = enumeration.nextRecordId();
428: byte[] data = rs.getRecord(tmpid);
429:
430: ByteArrayInputStream bis = new ByteArrayInputStream(data);
431: DataInputStream dis = new DataInputStream(bis);
432:
433: t.put(dis.readUTF(),dis.readUTF());
434: dis.close();
435: bis.close();
436: }
437: enumeration.destroy();
438: return t;
439: }
440: */
441:
442: private static Vector hkeys(RecordStore rs) throws Exception {
443: Vector v = new Vector();
444:
445: RecordEnumeration enumeration = rs.enumerateRecords(null, null,
446: false);
447: for (int i = 0; i < enumeration.numRecords(); i++) {
448: int tmpid = enumeration.nextRecordId();
449: byte[] data = rs.getRecord(tmpid);
450:
451: ByteArrayInputStream bis = new ByteArrayInputStream(data);
452: DataInputStream dis = new DataInputStream(bis);
453:
454: v.addElement(dis.readUTF());
455: dis.close();
456: bis.close();
457: }
458: return v;
459: }
460:
461: public static Object[] recordOf(RecordStore rs, String key)
462: throws Exception {
463: String value = null;
464: int id = -1;
465: RecordEnumeration enumeration = rs.enumerateRecords(null, null,
466: false);
467: for (int i = 0; i < enumeration.numRecords(); i++) {
468: int tmpid = enumeration.nextRecordId();
469: byte[] data = rs.getRecord(tmpid);
470:
471: ByteArrayInputStream bis = new ByteArrayInputStream(data);
472: DataInputStream dis = new DataInputStream(bis);
473:
474: String tmpkey = dis.readUTF();
475: bis.close();
476: dis.close();
477: if (tmpkey.equals(key)) {
478: id = tmpid;
479: value = dis.readUTF();
480: break;
481: }
482: }
483: enumeration.destroy();
484: return new Object[] { new Integer(id), value };
485: }
486:
487: public static void load(Interp ip) throws HeclException {
488: Operator.load(ip, cmdtable);
489: }
490:
491: public static void unload(Interp ip) throws HeclException {
492: Operator.unload(ip, cmdtable);
493: }
494:
495: private static Hashtable cmdtable = new Hashtable();
496:
497: static {
498: cmdtable.put("rms.list", new RMSCmd(RMS_LIST, 0, 1));
499: cmdtable.put("rms.create", new RMSCmd(RMS_CREATE, 1, 0));
500: cmdtable.put("rms.get", new RMSCmd(RMS_GET, 1, 2));
501: cmdtable.put("rms.set", new RMSCmd(RMS_SET, 2, 3));
502: cmdtable.put("rms.size", new RMSCmd(RMS_SIZE, 1, 1));
503: cmdtable.put("rms.sizeavail", new RMSCmd(RMS_SIZEAVAIL, 1, 1));
504: cmdtable.put("rms.delete", new RMSCmd(RMS_DELETE, 1, 2));
505: cmdtable.put("rms.add", new RMSCmd(RMS_ADD, 2, 2));
506: cmdtable.put("rms.hset", new RMSCmd(RMS_HSET, 3, 3));
507: cmdtable.put("rms.hget", new RMSCmd(RMS_HGET, 2, 2));
508: cmdtable.put("rms.hexists", new RMSCmd(RMS_HEXISTS, 2, 2));
509: cmdtable.put("rms.hkeys", new RMSCmd(RMS_HKEYS, 1, 1));
510: cmdtable.put("rms.hdel", new RMSCmd(RMS_HDEL, 2, 2));
511: //#if midp >= 2.0
512: cmdtable.put("rms.setmode", new RMSCmd(RMS_SETMODE, 3, 3));
513: //#endif
514: }
515: }
|