1//
2//  ========================================================================
3//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4//  ------------------------------------------------------------------------
5//  All rights reserved. This program and the accompanying materials
6//  are made available under the terms of the Eclipse Public License v1.0
7//  and Apache License v2.0 which accompanies this distribution.
8//
9//      The Eclipse Public License is available at
10//      http://www.eclipse.org/legal/epl-v10.html
11//
12//      The Apache License v2.0 is available at
13//      http://www.opensource.org/licenses/apache2.0.php
14//
15//  You may elect to redistribute this code under either of these licenses.
16//  ========================================================================
17//
18
19package org.eclipse.jetty.io.nio;
20
21import java.io.File;
22import java.io.FileNotFoundException;
23import java.io.IOException;
24import java.io.RandomAccessFile;
25import java.nio.channels.FileChannel;
26import java.nio.channels.WritableByteChannel;
27
28import org.eclipse.jetty.io.AbstractBuffer;
29import org.eclipse.jetty.io.Buffer;
30
31public class RandomAccessFileBuffer extends AbstractBuffer implements Buffer
32{
33    final RandomAccessFile _file;
34    final FileChannel _channel;
35    final int _capacity;
36
37    public RandomAccessFileBuffer(File file)
38        throws FileNotFoundException
39    {
40        super(READWRITE,true);
41        assert file.length()<=Integer.MAX_VALUE;
42        _file = new RandomAccessFile(file,"rw");
43        _channel=_file.getChannel();
44        _capacity=Integer.MAX_VALUE;
45        setGetIndex(0);
46        setPutIndex((int)file.length());
47    }
48
49    public RandomAccessFileBuffer(File file,int capacity)
50        throws FileNotFoundException
51    {
52        super(READWRITE,true);
53        assert capacity>=file.length();
54        assert file.length()<=Integer.MAX_VALUE;
55        _capacity=capacity;
56        _file = new RandomAccessFile(file,"rw");
57        _channel=_file.getChannel();
58        setGetIndex(0);
59        setPutIndex((int)file.length());
60    }
61
62    public RandomAccessFileBuffer(File file,int capacity,int access)
63        throws FileNotFoundException
64    {
65        super(access,true);
66        assert capacity>=file.length();
67        assert file.length()<=Integer.MAX_VALUE;
68        _capacity=capacity;
69        _file = new RandomAccessFile(file,access==READWRITE?"rw":"r");
70        _channel=_file.getChannel();
71        setGetIndex(0);
72        setPutIndex((int)file.length());
73    }
74
75    public byte[] array()
76    {
77        return null;
78    }
79
80    public int capacity()
81    {
82        return _capacity;
83    }
84
85    @Override
86    public void clear()
87    {
88        try
89        {
90            synchronized (_file)
91            {
92                super.clear();
93                _file.setLength(0);
94            }
95        }
96        catch(Exception e)
97        {
98            throw new RuntimeException(e);
99        }
100    }
101
102
103    @Override
104    public byte peek()
105    {
106        synchronized (_file)
107        {
108            try
109            {
110                if (_get!=_file.getFilePointer())
111                    _file.seek(_get);
112                return _file.readByte();
113            }
114            catch(Exception e)
115            {
116                throw new RuntimeException(e);
117            }
118        }
119    }
120
121    public byte peek(int index)
122    {
123        synchronized (_file)
124        {
125            try
126            {
127                _file.seek(index);
128                return _file.readByte();
129            }
130            catch(Exception e)
131            {
132                throw new RuntimeException(e);
133            }
134        }
135    }
136
137    public int peek(int index, byte[] b, int offset, int length)
138    {
139        synchronized (_file)
140        {
141            try
142            {
143                _file.seek(index);
144                return _file.read(b,offset,length);
145            }
146            catch(Exception e)
147            {
148                throw new RuntimeException(e);
149            }
150        }
151    }
152
153    public void poke(int index, byte b)
154    {
155        synchronized (_file)
156        {
157            try
158            {
159                _file.seek(index);
160                _file.writeByte(b);
161            }
162            catch(Exception e)
163            {
164                throw new RuntimeException(e);
165            }
166        }
167    }
168
169    @Override
170    public int poke(int index, byte[] b, int offset, int length)
171    {
172        synchronized (_file)
173        {
174            try
175            {
176                _file.seek(index);
177                _file.write(b,offset,length);
178                return length;
179            }
180            catch(Exception e)
181            {
182                throw new RuntimeException(e);
183            }
184        }
185    }
186
187    public int writeTo(WritableByteChannel channel,int index, int length)
188        throws IOException
189    {
190        synchronized (_file)
191        {
192            return (int)_channel.transferTo(index,length,channel);
193        }
194    }
195
196}
197