1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.microemu.app.util;
21
22 import java.io.DataInputStream;
23 import java.io.DataOutputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.FileOutputStream;
28 import java.io.FilenameFilter;
29 import java.io.IOException;
30 import java.security.AccessControlContext;
31 import java.security.AccessController;
32 import java.security.PrivilegedActionException;
33 import java.security.PrivilegedExceptionAction;
34 import java.util.Hashtable;
35
36 import javax.microedition.rms.RecordStore;
37 import javax.microedition.rms.RecordStoreException;
38 import javax.microedition.rms.RecordStoreNotFoundException;
39 import javax.microedition.rms.RecordStoreNotOpenException;
40
41 import org.microemu.MicroEmulator;
42 import org.microemu.RecordStoreManager;
43 import org.microemu.app.Config;
44 import org.microemu.log.Logger;
45 import org.microemu.util.ExtendedRecordListener;
46 import org.microemu.util.RecordStoreImpl;
47
48 public class FileRecordStoreManager implements RecordStoreManager {
49
50 private final static String RECORD_STORE_SUFFIX = ".rs";
51
52 private MicroEmulator emulator;
53
54 private Hashtable testOpenRecordStores = new Hashtable();
55
56 private ExtendedRecordListener recordListener = null;
57
58
59 private AccessControlContext acc;
60
61 private FilenameFilter filter = new FilenameFilter() {
62 public boolean accept(File dir, String name) {
63 if (name.endsWith(RECORD_STORE_SUFFIX)) {
64 return true;
65 } else {
66 return false;
67 }
68 }
69 };
70
71 public void init(MicroEmulator emulator) {
72 this.emulator = emulator;
73 this.acc = AccessController.getContext();
74 }
75
76 public String getName() {
77 return "File record store";
78 }
79
80 private File getSuiteFolder() {
81 return new File(Config.getConfigPath(), "suite-" + emulator.getLauncher().getSuiteName());
82 }
83
84 public void deleteRecordStore(final String recordStoreName) throws RecordStoreNotFoundException,
85 RecordStoreException {
86 final File storeFile = new File(getSuiteFolder(), recordStoreName + RECORD_STORE_SUFFIX);
87
88 RecordStoreImpl recordStoreImpl = (RecordStoreImpl) testOpenRecordStores.get(storeFile.getName());
89 if (recordStoreImpl != null && recordStoreImpl.isOpen()) {
90 throw new RecordStoreException();
91 }
92
93 try {
94 recordStoreImpl = loadFromDisk(storeFile);
95 } catch (FileNotFoundException ex) {
96 throw new RecordStoreNotFoundException(recordStoreName);
97 }
98
99 try {
100 AccessController.doPrivileged(new PrivilegedExceptionAction() {
101 public Object run() throws FileNotFoundException {
102 storeFile.delete();
103 fireRecordStoreListener(ExtendedRecordListener.RECORDSTORE_DELETE, recordStoreName);
104 return null;
105 }
106 }, acc);
107 } catch (PrivilegedActionException e) {
108 Logger.error("Unable remove file " + storeFile, e);
109 throw new RecordStoreException();
110 }
111 }
112
113 public RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) throws RecordStoreException {
114 File storeFile = new File(getSuiteFolder(), recordStoreName + RECORD_STORE_SUFFIX);
115
116 RecordStoreImpl recordStoreImpl;
117 try {
118 recordStoreImpl = loadFromDisk(storeFile);
119 } catch (FileNotFoundException e) {
120 if (!createIfNecessary) {
121 throw new RecordStoreNotFoundException(recordStoreName);
122 }
123 recordStoreImpl = new RecordStoreImpl(this, recordStoreName);
124 saveToDisk(storeFile, recordStoreImpl);
125 }
126 recordStoreImpl.setOpen(true);
127 if (recordListener != null) {
128 recordStoreImpl.addRecordListener(recordListener);
129 }
130
131 testOpenRecordStores.put(storeFile.getName(), recordStoreImpl);
132
133 fireRecordStoreListener(ExtendedRecordListener.RECORDSTORE_OPEN, recordStoreName);
134
135 return recordStoreImpl;
136 }
137
138 public String[] listRecordStores() {
139 String[] result;
140 try {
141 result = (String[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
142 public Object run() {
143 return getSuiteFolder().list(filter);
144 }
145 }, acc);
146 } catch (PrivilegedActionException e) {
147 Logger.error("Unable to acess storeFiles", e);
148 return null;
149 }
150 if (result != null) {
151 if (result.length == 0) {
152 result = null;
153 } else {
154 for (int i = 0; i < result.length; i++) {
155 result[i] = result[i].substring(0, result[i].length() - RECORD_STORE_SUFFIX.length());
156 }
157 }
158 }
159 return result;
160 }
161
162 public void saveChanges(RecordStoreImpl recordStoreImpl) throws RecordStoreNotOpenException, RecordStoreException {
163
164 File storeFile = new File(getSuiteFolder(), recordStoreImpl.getName() + RECORD_STORE_SUFFIX);
165
166 saveToDisk(storeFile, recordStoreImpl);
167 }
168
169 public void init() {
170 }
171
172 public void deleteStores() {
173 String[] stores = listRecordStores();
174 for (int i = 0; i < stores.length; i++) {
175 String store = stores[i];
176 try {
177 deleteRecordStore(store);
178 } catch (RecordStoreException e) {
179 Logger.debug("deleteRecordStore", e);
180 }
181 }
182 }
183
184 private RecordStoreImpl loadFromDisk(final File recordStoreFile) throws FileNotFoundException {
185 try {
186 return (RecordStoreImpl) AccessController.doPrivileged(new PrivilegedExceptionAction() {
187 public Object run() throws FileNotFoundException {
188 return loadFromDiskSecure(recordStoreFile);
189 }
190 }, acc);
191 } catch (PrivilegedActionException e) {
192 if (e.getCause() instanceof FileNotFoundException) {
193 throw (FileNotFoundException) e.getCause();
194 }
195 Logger.error("Unable access file " + recordStoreFile, e);
196 throw new FileNotFoundException();
197 }
198 }
199
200 private RecordStoreImpl loadFromDiskSecure(File recordStoreFile) throws FileNotFoundException {
201 RecordStoreImpl store = null;
202 try {
203 DataInputStream dis = new DataInputStream(new FileInputStream(recordStoreFile));
204 store = new RecordStoreImpl(this, dis);
205 dis.close();
206 } catch (FileNotFoundException e) {
207 throw e;
208 } catch (IOException e) {
209 Logger.error("RecordStore.loadFromDisk: ERROR reading " + recordStoreFile.getName(), e);
210 }
211 return store;
212 }
213
214 private void saveToDisk(final File recordStoreFile, final RecordStoreImpl recordStore) throws RecordStoreException {
215 try {
216 AccessController.doPrivileged(new PrivilegedExceptionAction() {
217 public Object run() throws RecordStoreException {
218 saveToDiskSecure(recordStoreFile, recordStore);
219 return null;
220 }
221 }, acc);
222 } catch (PrivilegedActionException e) {
223 if (e.getCause() instanceof RecordStoreException) {
224 throw (RecordStoreException) e.getCause();
225 }
226 Logger.error("Unable access file " + recordStoreFile, e);
227 throw new RecordStoreException();
228 }
229 }
230
231 private void saveToDiskSecure(final File recordStoreFile, final RecordStoreImpl recordStore)
232 throws RecordStoreException {
233 if (!recordStoreFile.getParentFile().exists()) {
234 if (!recordStoreFile.getParentFile().mkdirs()) {
235 throw new RecordStoreException("Unable to create recordStore directory");
236 }
237 }
238 try {
239 DataOutputStream dos = new DataOutputStream(new FileOutputStream(recordStoreFile));
240 recordStore.write(dos);
241 dos.close();
242 } catch (IOException e) {
243 Logger.error("RecordStore.saveToDisk: ERROR writting object to " + recordStoreFile.getName(), e);
244 throw new RecordStoreException(e.getMessage());
245 }
246 }
247
248 public int getSizeAvailable(RecordStoreImpl recordStoreImpl) {
249
250 return 1024 * 1024;
251 }
252
253 public void setRecordListener(ExtendedRecordListener recordListener) {
254 this.recordListener = recordListener;
255 }
256
257 public void fireRecordStoreListener(int type, String recordStoreName) {
258 if (recordListener != null) {
259 recordListener.recordStoreEvent(type, System.currentTimeMillis(), recordStoreName);
260 }
261 }
262 }