• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package java.io;
18 
19 import com.google.gwt.storage.client.Storage;
20 
21 /** Saves binary data to the local storage; currently using hex encoding. The string is prefixed with "hex:"
22  * @author haustein */
23 public class RandomAccessFile /* implements DataOutput, DataInput, Closeable */{
24 
25 /*
26  * public final FileDescriptor getFD() throws IOException { } public final FileChannel getChannel() { }
27  */
28 	final String name;
29 	final boolean writeable;
30 	boolean dirty;
31 	String data;
32 	int newDataPos;
33 	StringBuilder newData;
34 	int pos;
35 	int len;
36 
37 	DataInputStream dis = new DataInputStream(new RafInputStream());
38 	DataOutputStream dos = new DataOutputStream(new RafOutputStream());
39 
RandomAccessFile(String name, String mode)40 	public RandomAccessFile (String name, String mode) throws FileNotFoundException {
41 		this(new File(name), mode);
42 	}
43 
RandomAccessFile(File file, String mode)44 	public RandomAccessFile (File file, String mode) throws FileNotFoundException {
45 		name = file.getCanonicalPath();
46 
47 		mode = mode.toLowerCase();
48 		if (!mode.equals("r") && !mode.equals("rw")) {
49 			throw new IllegalArgumentException("mode: '" + mode + "'");
50 		}
51 		writeable = mode.equals("rw");
52 		if (file.exists()) {
53 			data = atob(File.LocalStorage.getItem(name));
54 			len = data.length();
55 		} else if (writeable) {
56 			data = "";
57 			dirty = true;
58 			try {
59 				flush();
60 			} catch (IOException e) {
61 				throw new FileNotFoundException("" + e);
62 			}
63 		} else {
64 			throw new FileNotFoundException(name);
65 		}
66 	}
67 
btoa(String s)68 	static native String btoa (String s) /*-{
69 														return $wnd.btoa(s);
70 														}-*/;
71 
atob(String s)72 	static native String atob (String s) /*-{
73 														return $wnd.atob(s);
74 														}-*/;
75 
read()76 	public int read () throws IOException {
77 		return dis.read();
78 	}
79 
read(byte b[], int off, int len)80 	public int read (byte b[], int off, int len) throws IOException {
81 		return dis.read(b, off, len);
82 	}
83 
read(byte b[])84 	public int read (byte b[]) throws IOException {
85 		return dis.read(b);
86 	}
87 
readFully(byte b[])88 	public final void readFully (byte b[]) throws IOException {
89 		dis.readFully(b);
90 	}
91 
readFully(byte b[], int off, int len)92 	public final void readFully (byte b[], int off, int len) throws IOException {
93 		dis.readFully(b, off, len);
94 	}
95 
skipBytes(int n)96 	public int skipBytes (int n) throws IOException {
97 		return dis.skipBytes(n);
98 	}
99 
write(int b)100 	public void write (int b) throws IOException {
101 		dos.write(b);
102 	};
103 
write(byte b[])104 	public void write (byte b[]) throws IOException {
105 		dos.write(b);
106 	}
107 
write(byte b[], int off, int len)108 	public void write (byte b[], int off, int len) throws IOException {
109 		dos.write(b, off, len);
110 	}
111 
getFilePointer()112 	public long getFilePointer () throws IOException {
113 		return pos;
114 	}
115 
seek(long pos)116 	public void seek (long pos) throws IOException {
117 		if (pos < 0) {
118 			throw new IllegalArgumentException();
119 		}
120 		this.pos = (int)pos;
121 	}
122 
length()123 	public long length () throws IOException {
124 		return len;
125 	}
126 
setLength(long newLength)127 	public void setLength (long newLength) throws IOException {
128 		if (len != newLength) {
129 			consolidate();
130 			if (data.length() > newLength) {
131 				data = data.substring(0, (int)newLength);
132 				len = (int)newLength;
133 			} else {
134 // System.out.println("padding " + (newLength - len) + " zeros in setLength to " + newLength);
135 				while (len < newLength) {
136 					write(0);
137 				}
138 			}
139 		}
140 	}
141 
close()142 	public void close () throws IOException {
143 		if (data != null) {
144 			flush();
145 			data = null;
146 		}
147 	}
148 
consolidate()149 	void consolidate () {
150 		if (newData == null) {
151 			return;
152 		}
153 
154 // System.out.println("consolidate(); ndp: " + newDataPos + " nd-len: " + newData.length());
155 
156 		if (data.length() < newDataPos) {
157 			StringBuilder filler = new StringBuilder();
158 			while (data.length() + filler.length() < newDataPos) {
159 				filler.append('\0');
160 			}
161 // System.out.println("padding " + (filler.length()) + " zeros in consolidate ");
162 
163 			data += filler.toString();
164 		}
165 
166 		int p2 = newDataPos + newData.length();
167 		data = data.substring(0, newDataPos) + newData.toString() + (p2 < data.length() ? data.substring(p2) : "");
168 		newData = null;
169 	}
170 
flush()171 	void flush () throws IOException {
172 		if (!dirty) {
173 			return;
174 		}
175 		consolidate();
176 		File.LocalStorage.setItem(name, btoa(data));
177 		dirty = false;
178 	}
179 
readBoolean()180 	public final boolean readBoolean () throws IOException {
181 		return dis.readBoolean();
182 	}
183 
readByte()184 	public final byte readByte () throws IOException {
185 		return dis.readByte();
186 	}
187 
readUnsignedByte()188 	public final int readUnsignedByte () throws IOException {
189 		return dis.readUnsignedByte();
190 	}
191 
readShort()192 	public final short readShort () throws IOException {
193 		return dis.readShort();
194 	}
195 
readUnsignedShort()196 	public final int readUnsignedShort () throws IOException {
197 		return dis.readUnsignedShort();
198 	}
199 
readChar()200 	public final char readChar () throws IOException {
201 		return dis.readChar();
202 	}
203 
readInt()204 	public final int readInt () throws IOException {
205 		return dis.readInt();
206 	}
207 
readLong()208 	public final long readLong () throws IOException {
209 		return dis.readLong();
210 	}
211 
readFloat()212 	public final float readFloat () throws IOException {
213 		return dis.readFloat();
214 	}
215 
readDouble()216 	public final double readDouble () throws IOException {
217 		return dis.readDouble();
218 	}
219 
readLine()220 	public final String readLine () throws IOException {
221 		return dis.readLine();
222 	}
223 
readUTF()224 	public final String readUTF () throws IOException {
225 		return dis.readUTF();
226 	}
227 
writeBoolean(boolean v)228 	public final void writeBoolean (boolean v) throws IOException {
229 		dos.writeBoolean(v);
230 	}
231 
writeByte(int v)232 	public final void writeByte (int v) throws IOException {
233 		dos.writeByte(v);
234 	}
235 
writeShort(int v)236 	public final void writeShort (int v) throws IOException {
237 		dos.writeShort(v);
238 	}
239 
writeChar(int v)240 	public final void writeChar (int v) throws IOException {
241 		dos.writeChar(v);
242 	}
243 
writeInt(int v)244 	public final void writeInt (int v) throws IOException {
245 		dos.writeInt(v);
246 	}
247 
writeLong(long v)248 	public final void writeLong (long v) throws IOException {
249 		dos.writeLong(v);
250 	}
251 
writeFloat(float v)252 	public final void writeFloat (float v) throws IOException {
253 		dos.writeFloat(v);
254 	}
255 
writeDouble(double v)256 	public final void writeDouble (double v) throws IOException {
257 		dos.writeDouble(v);
258 	}
259 
writeBytes(String s)260 	public final void writeBytes (String s) throws IOException {
261 		dos.writeBytes(s);
262 	}
263 
writeChars(String s)264 	public final void writeChars (String s) throws IOException {
265 		dos.writeChars(s);
266 	}
267 
writeUTF(String str)268 	public final void writeUTF (String str) throws IOException {
269 		dos.writeUTF(str);
270 	}
271 
272 // public final FileChannel getChannel() throws IOException { }
273 
274 	class RafInputStream extends InputStream {
275 		@Override
read()276 		public int read () throws IOException {
277 			if (pos >= len) {
278 				return -1;
279 			} else {
280 				consolidate();
281 				return data.charAt(pos++);
282 // int p2 = (pos << 1);
283 // int result = Character.digit(data.charAt(p2), 16) * 16 +
284 // Character.digit(data.charAt(p2 + 1), 16);
285 // pos++;
286 // return result;
287 			}
288 		}
289 	}
290 
291 	class RafOutputStream extends OutputStream {
292 
write(int b)293 		public void write (int b) throws IOException {
294 			if (!writeable) {
295 				throw new IOException("not writeable");
296 			}
297 
298 			if (newData == null) {
299 				newDataPos = pos;
300 				newData = new StringBuilder();
301 // System.out.println("no buf; newDataPos: " + pos);
302 			} else if (newDataPos + newData.length() != pos) {
303 				consolidate();
304 				newDataPos = pos;
305 				newData = new StringBuilder();
306 // System.out.println("pos mismatch; newDataPos: " + pos);
307 			}
308 
309 			newData.append((char)(b & 255));
310 // newData.append("" + Character.forDigit((b >> 4) & 15, 16) +
311 // Character.forDigit(b & 15, 16));
312 			pos++;
313 			len = Math.max(pos, len);
314 			dirty = true;
315 		}
316 	}
317 }
318