001: /*
002: * Copyright (c) 2007, Sun Microsystems, Inc.
003: *
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * * Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: * * Neither the name of Sun Microsystems, Inc. nor the names of its
017: * contributors may be used to endorse or promote products derived
018: * from this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
023: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
024: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.mmademo;
033:
034: import java.io.*;
035: import java.util.*;
036: import javax.microedition.rms.*;
037: import javax.microedition.midlet.*;
038: import javax.microedition.lcdui.*;
039: import javax.microedition.media.*;
040:
041: /**
042: * A RecordStore (RMS) browser. Used in SimplePlayer.
043: * <p>
044: * Pseudo URLs are used:<br>
045: * <code>rms:/RecordStoreName#index</code>
046: * <p>
047: * Examples:<br>
048: * <code>rms:/TheStorage#3</code> - to get index 3 in RecordStore named "TheStorage"<br>
049: * <code>rms:/</code> - to list all RecordStores<br>
050: * <code>rms:/TheStorage</code> - to list the indexes in RecordStore named "TheStorage"<br>
051: *
052: * @version 1.2
053: */
054: class SimpleRmsBrowser extends List implements CommandListener,
055: Utils.ContentHandler {
056:
057: private Command backCommand = new Command("Back", Command.BACK, 1);
058: private Command selCommand = new Command("Select", Command.ITEM, 1);
059: private Command delCommand = new Command("Delete", Command.ITEM, 1);
060:
061: // if this is set, then display indexes inside RecordStore
062: private int lastSelectedRecord;
063: private RecordStore currStore;
064: private String[] names;
065: private Utils.BreadCrumbTrail parent;
066:
067: public SimpleRmsBrowser(String title, Utils.BreadCrumbTrail parent) {
068: super (title, Choice.IMPLICIT);
069: this .parent = parent;
070: }
071:
072: public void display(String url, int selectedIndex) {
073: clearLists();
074: try {
075: String[] sURL = splitURL(url);
076: // don't allow different protocols, or a host/port
077: if (!canHandle(sURL)) {
078: throw new Exception("Invalid rms URL");
079: }
080: if (sURL[5] != "") {
081: throw new Exception("is a record, not a store");
082: }
083: if (sURL[4] != "") {
084: currStore = getRecordStore(sURL, false);
085: }
086: if (currStore != null) {
087: RecordEnumeration re = currStore.enumerateRecords(null,
088: null, false);
089: names = new String[re.numRecords()];
090: for (int i = 0; i < names.length; i++) {
091: try {
092: int id = re.nextRecordId();
093: names[i] = String.valueOf(id);
094: append(names[i] + " - "
095: + currStore.getRecordSize(id)
096: + " bytes", null);
097: } catch (InvalidRecordIDException irie) {
098: append("[invalid record ID]", null);
099: }
100: }
101: if (size() == 0) {
102: throw new Exception("no records");
103: }
104: } else {
105: names = RecordStore.listRecordStores();
106: if (names != null && names.length > 0) {
107: for (int i = 0; i < names.length; i++) {
108: append(names[i], null);
109: }
110: }
111: if (size() == 0) {
112: throw new Exception("No record stores!");
113: }
114: }
115: } catch (Throwable t) {
116: append("[" + Utils.friendlyException(t) + "]", null);
117: }
118: setListIndex(selectedIndex);
119: addCommand(backCommand);
120: addCommand(selCommand);
121: addCommand(delCommand);
122: setCommandListener(this );
123: }
124:
125: private void setListIndex(int index) {
126: if (index >= 0 && index < size()) {
127: setSelectedIndex(index, true);
128: }
129: }
130:
131: private void goBack() {
132: if (currStore != null) {
133: // display all record stores
134: display("rms:/", lastSelectedRecord);
135: } else {
136: exit();
137: }
138: }
139:
140: private void exit() {
141: clearLists();
142: parent.goBack();
143: }
144:
145: private void clearLists() {
146: if (currStore != null) {
147: try {
148: currStore.closeRecordStore();
149: } catch (Exception e) {
150: Utils.debugOut(e);
151: }
152: currStore = null;
153: }
154: names = null;
155: for (int i = size() - 1; i >= 0; i--) {
156: delete(i);
157: }
158: // good moment to garbage collect
159: System.gc();
160: }
161:
162: // interface Utils.ContentHandler
163: public void close() {
164: clearLists();
165: }
166:
167: // interface Utils.ContentHandler
168: public boolean canHandle(String url) {
169: try {
170: Utils.debugOut("SimpleRmsBrowser.canHandle: isValidRmsURL("
171: + url + ") = " + isValidRmsURL(splitURL(url)));
172: return canHandle(splitURL(url));
173: } catch (Exception e) {
174: }
175: return false;
176: }
177:
178: // interface Utils.ContentHandler
179: public void handle(String name, String url) {
180: Utils.debugOut("SimpleRmsBrowser: handle " + url);
181: display(url, 0);
182: }
183:
184: private static boolean canHandle(String[] sURL) {
185: try {
186: return isValidRmsURL(sURL) && sURL[5] == ""; // anchor (contains index in recordstore)
187: } catch (Exception e) {
188: }
189: return false;
190: }
191:
192: private static boolean isValidRmsURL(String[] sURL) {
193: boolean res = sURL[0].equals("rms") // protocol
194: && sURL[1] == "" // host
195: && sURL[2] == "" // port
196: && (sURL[3] == "" || sURL[3].equals("/")); // path
197: // if index is set, then record store name must be set, too
198: if (res && sURL[5] != "" && sURL[4] == "") {
199: res = false;
200: }
201: return res;
202: }
203:
204: /**
205: * @return true if the URL points to a file, i.e. Record Store name + Index
206: */
207: public static boolean isRmsFile(String url) {
208: try {
209: String[] sURL = splitURL(url);
210: return isValidRmsURL(sURL) && sURL[4] != ""
211: && sURL[5] != "";
212: } catch (Exception e) {
213: }
214: return false;
215: }
216:
217: private static String[] splitURL(String url) throws Exception {
218: String[] sURL = Utils.splitURL(url);
219: // if filename is empty, but path exists, then
220: // the path is actually the filename (name of record store)
221: if (sURL[4] == "" && sURL[3] != "") {
222: sURL[4] = sURL[3];
223: sURL[3] = "";
224: }
225: if (sURL[4].startsWith("/")) {
226: sURL[4] = sURL[4].substring(1);
227: }
228: return sURL;
229: }
230:
231: /**
232: * Respond to commands
233: */
234: public void commandAction(Command c, Displayable s) {
235: try {
236: if (((c == List.SELECT_COMMAND) || c == selCommand)
237: && isShown()) {
238: select(getSelectedIndex());
239: } else if (c == backCommand) {
240: goBack();
241: } else if (c == delCommand) {
242: deleteRecord(getSelectedIndex());
243: }
244: } catch (Throwable t) {
245: //
246: }
247: }
248:
249: private void select(int index) {
250: if (names == null || index < 0 || index >= names.length) {
251: goBack();
252: }
253: if (currStore != null) {
254: try {
255: String name = currStore.getName() + "#" + names[index];
256: parent.handle(name, "rms:/" + name);
257: } catch (Exception e) {
258: Utils.error(e, parent);
259: }
260: } else {
261: lastSelectedRecord = index;
262: display("rms:/" + names[index], 0);
263: }
264: }
265:
266: private void deleteRecord(int index) {
267: if (names == null || index < 0 || index >= names.length) {
268: // error message ?
269: return;
270: }
271: String name = "";
272: String disp = "";
273: try {
274: if (currStore != null) {
275: disp = "rms:/" + currStore.getName();
276: name = "Record " + names[index];
277: int i = Integer.parseInt(names[index]);
278: currStore.deleteRecord(i);
279: } else {
280: name = "Record Store " + names[index];
281: disp = "rms:/";
282: RecordStore.deleteRecordStore(names[index]);
283: }
284: Utils.FYI(name + " successfully deleted", parent);
285: } catch (Exception e) {
286: Utils.error(e, parent);
287: }
288: display(disp, 0);
289: }
290:
291: /////////////////////// RecordStore utilities ////////////////////////////////////////
292:
293: /**
294: * Callers must make sure to call closeRecordStore() !
295: */
296: public static RecordStore getRecordStore(String url,
297: boolean canCreate) throws Exception {
298: Utils.debugOut("url = " + url + " can create = " + canCreate);
299: return getRecordStore(splitURL(url), canCreate);
300: }
301:
302: private static RecordStore getRecordStore(String[] sURL,
303: boolean canCreate) throws Exception {
304: if (!isValidRmsURL(sURL)) {
305: throw new Exception("Invalid rms URL");
306: }
307: try {
308: Utils.debugOut("Trying to open Record Store " + sURL[4]
309: + " can create = " + canCreate);
310: return RecordStore.openRecordStore(sURL[4], canCreate);
311: } catch (RecordStoreNotFoundException rsnfe) {
312: throw new Exception("Recordstore not found");
313: }
314: }
315:
316: private static int getRecordStoreIndex(String[] sURL)
317: throws Exception {
318: if (!isValidRmsURL(sURL)) {
319: throw new Exception("Invalid rms URL");
320: }
321: int result = -1;
322: try {
323: result = Integer.parseInt(sURL[5]);
324: if (result < 0) {
325: throw new NumberFormatException();
326: }
327: } catch (NumberFormatException nfe) {
328: throw new Exception("invalid record store index");
329: }
330: return result;
331: }
332:
333: // throws Exception if url is malformed
334: public static int saveToRecordStore(InputStream is, String url)
335: throws IOException, RecordStoreException, Exception {
336: RecordStore rs = getRecordStore(splitURL(url), true);
337: int ret = 0;
338: try {
339: ret = saveToRecordStore(is, rs);
340: } finally {
341: rs.closeRecordStore();
342: }
343: return ret;
344: }
345:
346: public static int saveToRecordStore(InputStream is, RecordStore rs)
347: throws IOException, RecordStoreException {
348: byte[] buffer = new byte[1024];
349: ByteArrayOutputStream baos = new ByteArrayOutputStream();
350: while (true) {
351: int read = is.read(buffer);
352: if (read < 0) {
353: // finished reading
354: break;
355: }
356: baos.write(buffer, 0, read);
357: }
358: buffer = baos.toByteArray();
359: return rs.addRecord(buffer, 0, buffer.length);
360: }
361:
362: public static InputStream getRecordStoreStream(String url)
363: throws RecordStoreException, Exception {
364: Utils.debugOut("getRecordStoreStream(" + url + ")");
365: return getRecordStoreStream(splitURL(url));
366: }
367:
368: private static InputStream getRecordStoreStream(String[] sURL)
369: throws RecordStoreException, Exception {
370: InputStream is = null;
371: RecordStore rs = getRecordStore(sURL, false);
372: try {
373: int index = getRecordStoreIndex(sURL);
374: is = getRecordStoreStream(rs, index);
375: } finally {
376: rs.closeRecordStore();
377: }
378: return is;
379: }
380:
381: public static InputStream getRecordStoreStream(RecordStore rs,
382: int index) throws RecordStoreException, Exception {
383: byte[] buffer = rs.getRecord(index);
384: return new ByteArrayInputStream(buffer);
385: }
386:
387: // for debugging
388: public String toString() {
389: return "SimpleRmsBrowser";
390: }
391: }
|