View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs.provider.ram;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.DataInputStream;
21  import java.io.DataOutputStream;
22  import java.io.EOFException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  
26  import org.apache.commons.vfs.RandomAccessContent;
27  import org.apache.commons.vfs.util.RandomAccessMode;
28  
29  /***
30   * RAM File Random Access Content
31   */
32  public class RamFileRandomAccessContent implements RandomAccessContent
33  {
34  	/***
35  	 * Buffer
36  	 */
37  	byte[] buf;
38  
39  	/***
40  	 * File Pointer
41  	 */
42  	protected int filePointer = 0;
43  
44  	/***
45  	 * buffer
46  	 */
47  	private byte buffer8[] = new byte[8];
48  
49  	/***
50  	 * buffer
51  	 */
52  	private byte buffer4[] = new byte[4];
53  
54  	/***
55  	 * buffer
56  	 */
57  	private byte buffer2[] = new byte[2];
58  
59  	/***
60  	 * buffer
61  	 */
62  	private byte buffer1[] = new byte[1];
63  
64  	/***
65  	 * Mode
66  	 */
67  	private RandomAccessMode mode;
68  
69  	/***
70  	 * File
71  	 */
72  	private RamFileObject file;
73  
74  	private InputStream rafis;
75  
76  	/***
77  	 * @param mode
78  	 */
79  	public RamFileRandomAccessContent(RamFileObject file, RandomAccessMode mode)
80  	{
81  		super();
82  		this.buf = file.getData().getBuffer();
83  		this.file = file;
84  		this.mode = mode;
85  
86  		rafis = new InputStream()
87  		{
88  			public int read() throws IOException
89  			{
90  				try
91  				{
92  					return readByte();
93  				}
94  				catch (EOFException e)
95  				{
96  					return -1;
97  				}
98  			}
99  
100 			public long skip(long n) throws IOException
101 			{
102 				seek(getFilePointer() + n);
103 				return n;
104 			}
105 
106 			public void close() throws IOException
107 			{
108 				close();
109 			}
110 
111 			public int read(byte b[]) throws IOException
112 			{
113 				return read(b);
114 			}
115 
116 			public int read(byte b[], int off, int len) throws IOException
117 			{
118 				int retLen = Math.min(len, getLeftBytes());
119 				RamFileRandomAccessContent.this.readFully(b, off, retLen);
120 				return retLen;
121 			}
122 
123 			public int available() throws IOException
124 			{
125 				return getLeftBytes();
126 			}
127 		};
128 	}
129 
130 	/*
131 	 * (non-Javadoc)
132 	 * 
133 	 * @see org.apache.commons.vfs.RandomAccessContent#getFilePointer()
134 	 */
135 	public long getFilePointer() throws IOException
136 	{
137 		return this.filePointer;
138 	}
139 
140 	/*
141 	 * (non-Javadoc)
142 	 * 
143 	 * @see org.apache.commons.vfs.RandomAccessContent#seek(long)
144 	 */
145 	public void seek(long pos) throws IOException
146 	{
147 		this.filePointer = (int) pos;
148 	}
149 
150 	/*
151 	 * (non-Javadoc)
152 	 * 
153 	 * @see org.apache.commons.vfs.RandomAccessContent#length()
154 	 */
155 	public long length() throws IOException
156 	{
157 		return buf.length;
158 	}
159 
160 	/*
161 	 * (non-Javadoc)
162 	 * 
163 	 * @see org.apache.commons.vfs.RandomAccessContent#close()
164 	 */
165 	public void close() throws IOException
166 	{
167 
168 	}
169 
170 	/*
171 	 * (non-Javadoc)
172 	 * 
173 	 * @see java.io.DataInput#readByte()
174 	 */
175 	public byte readByte() throws IOException
176 	{
177 		return (byte) this.readUnsignedByte();
178 	}
179 
180 	/*
181 	 * (non-Javadoc)
182 	 * 
183 	 * @see java.io.DataInput#readChar()
184 	 */
185 	public char readChar() throws IOException
186 	{
187 		int ch1 = this.readUnsignedByte();
188 		int ch2 = this.readUnsignedByte();
189 		return (char) ((ch1 << 8) + (ch2 << 0));
190 	}
191 
192 	/*
193 	 * (non-Javadoc)
194 	 * 
195 	 * @see java.io.DataInput#readDouble()
196 	 */
197 	public double readDouble() throws IOException
198 	{
199 		return Double.longBitsToDouble(this.readLong());
200 	}
201 
202 	/*
203 	 * (non-Javadoc)
204 	 * 
205 	 * @see java.io.DataInput#readFloat()
206 	 */
207 	public float readFloat() throws IOException
208 	{
209 		return Float.intBitsToFloat(this.readInt());
210 	}
211 
212 	/*
213 	 * (non-Javadoc)
214 	 * 
215 	 * @see java.io.DataInput#readInt()
216 	 */
217 	public int readInt() throws IOException
218 	{
219 		return (readUnsignedByte() << 24) | (readUnsignedByte() << 16)
220 				| (readUnsignedByte() << 8) | readUnsignedByte();
221 	}
222 
223 	/*
224 	 * (non-Javadoc)
225 	 * 
226 	 * @see java.io.DataInput#readUnsignedByte()
227 	 */
228 	public int readUnsignedByte() throws IOException
229 	{
230 		if (filePointer < buf.length)
231 		{
232 			return buf[filePointer++] & 0xFF;
233 		}
234 		else
235 		{
236 			throw new EOFException();
237 		}
238 	}
239 
240 	/*
241 	 * (non-Javadoc)
242 	 * 
243 	 * @see java.io.DataInput#readUnsignedShort()
244 	 */
245 	public int readUnsignedShort() throws IOException
246 	{
247 		this.readFully(buffer2);
248 		return toUnsignedShort(buffer2);
249 	}
250 
251 	/*
252 	 * (non-Javadoc)
253 	 * 
254 	 * @see java.io.DataInput#readLong()
255 	 */
256 	public long readLong() throws IOException
257 	{
258 		this.readFully(buffer8);
259 		return toLong(buffer8);
260 	}
261 
262 	/*
263 	 * (non-Javadoc)
264 	 * 
265 	 * @see java.io.DataInput#readShort()
266 	 */
267 	public short readShort() throws IOException
268 	{
269 		this.readFully(buffer2);
270 		return toShort(buffer2);
271 	}
272 
273 	/*
274 	 * (non-Javadoc)
275 	 * 
276 	 * @see java.io.DataInput#readBoolean()
277 	 */
278 	public boolean readBoolean() throws IOException
279 	{
280 		return (this.readUnsignedByte() != 0);
281 	}
282 
283 	/*
284 	 * (non-Javadoc)
285 	 * 
286 	 * @see java.io.DataInput#skipBytes(int)
287 	 */
288 	public int skipBytes(int n) throws IOException
289 	{
290 		if (n < 0)
291 		{
292 			throw new IndexOutOfBoundsException(
293 					"The skip number can't be negative");
294 		}
295 
296 		long newPos = filePointer + n;
297 
298 		if (newPos > buf.length)
299 		{
300 			throw new IndexOutOfBoundsException("Tyring to skip too much bytes");
301 		}
302 
303 		seek(newPos);
304 
305 		return n;
306 	}
307 
308 	/*
309 	 * (non-Javadoc)
310 	 * 
311 	 * @see java.io.DataInput#readFully(byte[])
312 	 */
313 	public void readFully(byte[] b) throws IOException
314 	{
315 		this.readFully(b, 0, b.length);
316 	}
317 
318 	/*
319 	 * (non-Javadoc)
320 	 * 
321 	 * @see java.io.DataInput#readFully(byte[], int, int)
322 	 */
323 	public void readFully(byte[] b, int off, int len) throws IOException
324 	{
325 		if (len < 0)
326 		{
327 			throw new IndexOutOfBoundsException("Length is lower than 0");
328 		}
329 
330 		if (len > this.getLeftBytes())
331 		{
332 			throw new IndexOutOfBoundsException("Read length (" + len
333 					+ ") is higher than buffer left bytes ("
334 					+ this.getLeftBytes() + ") ");
335 		}
336 
337 		System.arraycopy(buf, filePointer, b, off, len);
338 
339 		filePointer += len;
340 	}
341 
342 	private int getLeftBytes()
343 	{
344 		return buf.length - filePointer;
345 	}
346 
347 	/*
348 	 * (non-Javadoc)
349 	 * 
350 	 * @see java.io.DataInput#readUTF()
351 	 */
352 	public String readUTF() throws IOException
353 	{
354 		return DataInputStream.readUTF(this);
355 	}
356 
357 	/*
358 	 * (non-Javadoc)
359 	 * 
360 	 * @see java.io.DataOutput#write(byte[], int, int)
361 	 */
362 	public void write(byte[] b, int off, int len) throws IOException
363 	{
364 		if (this.getLeftBytes() < len)
365 		{
366 			int newSize = this.buf.length + len - this.getLeftBytes();
367 			this.file.resize(newSize);
368 			this.buf = this.file.getData().getBuffer();
369 		}
370 		System.arraycopy(b, off, this.buf, filePointer, len);
371 		this.filePointer += len;
372 	}
373 
374 	/*
375 	 * (non-Javadoc)
376 	 * 
377 	 * @see java.io.DataOutput#write(byte[])
378 	 */
379 	public void write(byte[] b) throws IOException
380 	{
381 		this.write(b, 0, b.length);
382 	}
383 
384 	/*
385 	 * (non-Javadoc)
386 	 * 
387 	 * @see java.io.DataOutput#writeByte(int)
388 	 */
389 	public void writeByte(int i) throws IOException
390 	{
391 		this.write(i);
392 	}
393 
394 	/***
395 	 * Build a long from first 8 bytes of the array.
396 	 * 
397 	 * @author Apache-Commons-Id Team
398 	 * @param b
399 	 *            The byte[] to convert.
400 	 * @return A long.
401 	 */
402 	public static long toLong(byte[] b)
403 	{
404 		return ((((long) b[7]) & 0xFF) + ((((long) b[6]) & 0xFF) << 8)
405 				+ ((((long) b[5]) & 0xFF) << 16)
406 				+ ((((long) b[4]) & 0xFF) << 24)
407 				+ ((((long) b[3]) & 0xFF) << 32)
408 				+ ((((long) b[2]) & 0xFF) << 40)
409 				+ ((((long) b[1]) & 0xFF) << 48) + ((((long) b[0]) & 0xFF) << 56));
410 	}
411 
412 	/***
413 	 * Build a 8-byte array from a long. No check is performed on the array
414 	 * length.
415 	 * 
416 	 * @author Commons-Id Team
417 	 * 
418 	 * @param n
419 	 *            The number to convert.
420 	 * @param b
421 	 *            The array to fill.
422 	 * @return A byte[].
423 	 */
424 	public static byte[] toBytes(long n, byte[] b)
425 	{
426 		b[7] = (byte) (n);
427 		n >>>= 8;
428 		b[6] = (byte) (n);
429 		n >>>= 8;
430 		b[5] = (byte) (n);
431 		n >>>= 8;
432 		b[4] = (byte) (n);
433 		n >>>= 8;
434 		b[3] = (byte) (n);
435 		n >>>= 8;
436 		b[2] = (byte) (n);
437 		n >>>= 8;
438 		b[1] = (byte) (n);
439 		n >>>= 8;
440 		b[0] = (byte) (n);
441 		return b;
442 	}
443 
444 	/***
445 	 * Build a short from first 2 bytes of the array.
446 	 * 
447 	 * @author Apache-Commons-Id Team
448 	 * @param b
449 	 *            The byte[] to convert.
450 	 * @return A short.
451 	 */
452 	public static short toShort(byte[] b)
453 	{
454 		return (short) toUnsignedShort(b);
455 	}
456 
457 	/***
458 	 * Build a short from first 2 bytes of the array.
459 	 * 
460 	 * @author Apache-Commons-Id Team
461 	 * @param b
462 	 *            The byte[] to convert.
463 	 * @return A short.
464 	 */
465 	public static int toUnsignedShort(byte[] b)
466 	{
467 		return ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
468 	}
469 
470 	/*
471 	 * (non-Javadoc)
472 	 * 
473 	 * @see java.io.DataOutput#write(int)
474 	 */
475 	public void write(int b) throws IOException
476 	{
477 		buffer1[0] = (byte) b;
478 		this.write(buffer1);
479 	}
480 
481 	/*
482 	 * (non-Javadoc)
483 	 * 
484 	 * @see java.io.DataOutput#writeBoolean(boolean)
485 	 */
486 	public void writeBoolean(boolean v) throws IOException
487 	{
488 		this.write(v ? 1 : 0);
489 	}
490 
491 	/*
492 	 * (non-Javadoc)
493 	 * 
494 	 * @see java.io.DataOutput#writeBytes(java.lang.String)
495 	 */
496 	public void writeBytes(String s) throws IOException
497 	{
498 		write(s.getBytes());
499 	}
500 
501 	/*
502 	 * (non-Javadoc)
503 	 * 
504 	 * @see java.io.DataOutput#writeChar(int)
505 	 */
506 	public void writeChar(int v) throws IOException
507 	{
508 		buffer2[0] = (byte) ((v >>> 8) & 0xFF);
509 		buffer2[1] = (byte) ((v >>> 0) & 0xFF);
510 		write(buffer2);
511 	}
512 
513 	/*
514 	 * (non-Javadoc)
515 	 * 
516 	 * @see java.io.DataOutput#writeChars(java.lang.String)
517 	 */
518 	public void writeChars(String s) throws IOException
519 	{
520 		int len = s.length();
521 		for (int i = 0; i < len; i++)
522 		{
523 			writeChar(s.charAt(i));
524 		}
525 	}
526 
527 	/*
528 	 * (non-Javadoc)
529 	 * 
530 	 * @see java.io.DataOutput#writeDouble(double)
531 	 */
532 	public void writeDouble(double v) throws IOException
533 	{
534 		writeLong(Double.doubleToLongBits(v));
535 	}
536 
537 	/*
538 	 * (non-Javadoc)
539 	 * 
540 	 * @see java.io.DataOutput#writeFloat(float)
541 	 */
542 	public void writeFloat(float v) throws IOException
543 	{
544 		writeInt(Float.floatToIntBits(v));
545 	}
546 
547 	/*
548 	 * (non-Javadoc)
549 	 * 
550 	 * @see java.io.DataOutput#writeInt(int)
551 	 */
552 	public void writeInt(int v) throws IOException
553 	{
554 		buffer4[0] = (byte) ((v >>> 24) & 0xFF);
555 		buffer4[1] = (byte) ((v >>> 16) & 0xFF);
556 		buffer4[2] = (byte) ((v >>> 8) & 0xFF);
557 		buffer4[3] = (byte) (v & 0xFF);
558 		write(buffer4);
559 	}
560 
561 	/*
562 	 * (non-Javadoc)
563 	 * 
564 	 * @see java.io.DataOutput#writeLong(long)
565 	 */
566 	public void writeLong(long v) throws IOException
567 	{
568 		write(toBytes(v, buffer8));
569 	}
570 
571 	/*
572 	 * (non-Javadoc)
573 	 * 
574 	 * @see java.io.DataOutput#writeShort(int)
575 	 */
576 	public void writeShort(int v) throws IOException
577 	{
578 		buffer2[0] = (byte) ((v >>> 8) & 0xFF);
579 		buffer2[1] = (byte) (v & 0xFF);
580 		write(buffer2);
581 	}
582 
583 	/*
584 	 * (non-Javadoc)
585 	 * 
586 	 * @see java.io.DataOutput#writeUTF(java.lang.String)
587 	 */
588 	public void writeUTF(String str) throws IOException
589 	{
590 		ByteArrayOutputStream out = new ByteArrayOutputStream(str.length());
591 		DataOutputStream dataOut = new DataOutputStream(out);
592 		dataOut.writeUTF(str);
593 		dataOut.flush();
594 		dataOut.close();
595 		byte[] b = out.toByteArray();
596 		write(b);
597 	}
598 
599 	/*
600 	 * (non-Javadoc)
601 	 * 
602 	 * @see java.io.DataInput#readLine()
603 	 */
604 	public String readLine() throws IOException
605 	{
606 		throw new UnsupportedOperationException("deprecated");
607 	}
608 
609 	public InputStream getInputStream() throws IOException
610 	{
611 		return rafis;
612 	}
613 }