001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.vfs;
031:
032: import java.io.FileInputStream;
033: import java.io.FileOutputStream;
034: import java.io.IOException;
035: import java.io.InputStream;
036: import java.io.OutputStream;
037: import java.io.RandomAccessFile;
038:
039: import java.nio.channels.FileChannel;
040: import java.nio.channels.FileLock;
041:
042: import java.util.logging.Level;
043: import java.util.logging.Logger;
044:
045: /**
046: * Reads from a file in a random-access fashion.
047: */
048: public class FileRandomAccessStream extends RandomAccessStream
049: implements LockableStream {
050: private static final Logger log = Logger
051: .getLogger(FileRandomAccessStream.class.getName());
052:
053: private RandomAccessFile _file;
054: private OutputStream _os;
055: private InputStream _is;
056:
057: private FileLock _fileLock;
058: private FileChannel _fileChannel;
059:
060: public FileRandomAccessStream(RandomAccessFile file) {
061: _file = file;
062: }
063:
064: public RandomAccessFile getRandomAccessFile() {
065: return _file;
066: }
067:
068: /**
069: * Returns the length.
070: */
071: public long getLength() throws IOException {
072: return _file.length();
073: }
074:
075: /**
076: * Reads a block starting from the current file pointer.
077: */
078: public int read(byte[] buffer, int offset, int length)
079: throws IOException {
080: return _file.read(buffer, offset, length);
081: }
082:
083: /**
084: * Reads a block starting from the current file pointer.
085: */
086: public int read(char[] buffer, int offset, int length)
087: throws IOException {
088: byte[] bytes = new byte[length];
089:
090: int count = _file.read(bytes, 0, length);
091:
092: for (int i = 0; i < count; i++) {
093: buffer[offset + i] = (char) bytes[i];
094:
095: }
096:
097: return count;
098: }
099:
100: /**
101: * Reads a block from a given location.
102: */
103: public int read(long fileOffset, byte[] buffer, int offset,
104: int length) throws IOException {
105: _file.seek(fileOffset);
106:
107: return _file.read(buffer, offset, length);
108: }
109:
110: /**
111: * Writes a block starting from the current file pointer.
112: */
113: public void write(byte[] buffer, int offset, int length)
114: throws IOException {
115: _file.write(buffer, offset, length);
116: }
117:
118: /**
119: * Writes a block from a given location.
120: */
121: public void write(long fileOffset, byte[] buffer, int offset,
122: int length) throws IOException {
123: _file.seek(fileOffset);
124:
125: _file.write(buffer, offset, length);
126: }
127:
128: /**
129: * Seeks to the given position in the file.
130: */
131: public boolean seek(long position) {
132: try {
133: _file.seek(position);
134:
135: return true;
136: } catch (IOException e) {
137: return false;
138: }
139: }
140:
141: /**
142: * Returns an OutputStream for this stream.
143: */
144: public OutputStream getOutputStream() throws IOException {
145: if (_os == null)
146: _os = new FileOutputStream(_file.getFD());
147:
148: return _os;
149: }
150:
151: /**
152: * Returns an InputStream for this stream.
153: */
154: public InputStream getInputStream() throws IOException {
155: if (_is == null)
156: _is = new FileInputStream(_file.getFD());
157:
158: return _is;
159: }
160:
161: /**
162: * Read a byte from the file, advancing the pointer.
163: */
164: public int read() throws IOException {
165: return _file.read();
166: }
167:
168: /**
169: * Write a byte to the file, advancing the pointer.
170: */
171: public void write(int b) throws IOException {
172: _file.write(b);
173: }
174:
175: /**
176: * Returns the current position of the file pointer.
177: */
178: public long getFilePointer() throws IOException {
179: return _file.getFilePointer();
180: }
181:
182: /**
183: * Closes the stream.
184: */
185: public void close() throws IOException {
186: unlock();
187:
188: _fileChannel = null;
189:
190: RandomAccessFile file = _file;
191: _file = null;
192:
193: if (file != null)
194: file.close();
195: }
196:
197: public boolean lock(boolean shared, boolean block) {
198: unlock();
199:
200: try {
201: if (_fileChannel == null) {
202: _fileChannel = _file.getChannel();
203: }
204:
205: if (block)
206: _fileLock = _fileChannel
207: .lock(0, Long.MAX_VALUE, shared);
208: else
209: _fileLock = _fileChannel.tryLock(0, Long.MAX_VALUE,
210: shared);
211:
212: return _fileLock != null;
213: } catch (IOException e) {
214: log.log(Level.FINE, e.toString(), e);
215: return false;
216: }
217: }
218:
219: public boolean unlock() {
220: try {
221: FileLock lock = _fileLock;
222: _fileLock = null;
223:
224: if (lock != null) {
225: lock.release();
226:
227: return true;
228: }
229:
230: return false;
231: } catch (IOException e) {
232: log.log(Level.FINE, e.toString(), e);
233: return false;
234: }
235: }
236:
237: }
|