Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: juju/reattore/io/impl/ChannelFileSource.java


1   /*  Reattore HTTP Server
2   
3       Copyright (C) 2002 Michael Hope <michaelh@juju.net.nz>
4   
5       This program is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published by
7       the Free Software Foundation; either version 2 of the License, or
8       (at your option) any later version.
9   
10      This program is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13      GNU General Public License for more details.
14  
15      You should have received a copy of the GNU General Public License
16      along with this program; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  
19      $Id: ChannelFileSource.java,v 1.13 2003/02/22 04:29:52 michaelh Exp $
20  */
21  
22  package juju.reattore.io.impl;
23  
24  import java.io.*;
25  import java.nio.ByteBuffer;
26  import java.nio.channels.*;
27  
28  import juju.reattore.io.*;
29  
30  /** A byte source that serves from a file using channels.  Implemented
31      by reading the whole file into a byte buffer.
32  
33      @todo Minor: Cannot handle > 4GB files
34      @todo Doesn't implement get() for > readSize files
35   */
36  public class ChannelFileSource
37      implements FileSource, CachableSource, BulkByteSource {
38  
39      private Cache cache;
40  
41      private File file;
42      private FileChannel fch;
43      private int size;
44      private int readSize = 64 * 1024;
45  
46      private ByteBuffer bb;
47      private boolean oversized;
48      private boolean firstRead = true;
49  
50      private static final int CHECK_INTERVAL = 5;
51  
52      private long stamp;
53      private int checkIn = CHECK_INTERVAL;
54  
55      /** Create a new source around the given file.
56  
57          @param file   The file to wrap around.
58          @throws IOException if the file cannot be opened.
59      */
60      public ChannelFileSource(File file)
61          throws IOException {
62  
63          this.file = file;
64          
65          stamp = file.lastModified();
66  
67          FileInputStream fin = new FileInputStream(file);
68          fch = fin.getChannel();
69  
70          size = (int)fch.size();
71      }
72  
73      private void setup() {
74          if (bb == null) {
75              oversized = size > readSize;
76              bb = ByteBufferPool.allocate(oversized ? readSize : size);
77          }
78      }
79  
80      private void read() 
81          throws IOException {
82  
83          setup();
84  
85          if (firstRead || oversized) {
86              bb.clear();
87              fch.read(bb);
88  
89              bb.flip();
90          }
91  
92          firstRead = false;
93      }
94  
95      /** Test method that changes the maximum size a file may be before
96          it is chunked into parts.
97  
98          @param to  The maximum size in bytes.
99      */
100     public void setReadSize(int to) {
101         this.readSize = to;
102     }
103 
104     /** @see BulkByteSource */
105     public ByteBuffer getBulk() 
106         throws IOException {
107 
108         read();
109         return bb;
110     }
111 
112     /** @see ByteSource */
113     public int get() 
114         throws IOException {
115 
116         read();
117         assert oversized == false;
118 
119         return bb.get();
120     }
121 
122     /** @see ByteSource */
123     public int get(byte[] into, int offset, int length) 
124         throws IOException {
125 
126         read();
127         assert oversized == false;
128 
129         if (length > bb.remaining()) {
130             length = bb.remaining();
131         }
132 
133         bb.get(into, offset, length);
134 
135         return length;
136     }
137 
138     /** @see ByteSource */
139     public int remaining() 
140         throws IOException {
141 
142         setup();
143 
144         if (oversized) {
145             return (int)(size - fch.position());
146         }
147         else {
148             read();
149             return bb.remaining();
150         }
151     }
152 
153     /** @see CachableSource */
154     public void release() {
155         if (fch != null) {
156             try {
157                 fch.close();
158             }
159             catch (IOException ex) {
160                 /* Drop */
161             }
162             finally {
163                 fch = null;
164             }
165         }
166         if (bb != null) {
167             ByteBufferPool.release(bb);
168             bb = null;
169         }
170     }
171 
172     /** @see Source */
173     public void dispose() {
174         if (cache != null && cache.onClose(this) == false) {
175             /* The cache took us back */
176         }
177         else {
178             release();
179         }
180     }
181 
182     /** @see CachableSource */
183     public void rewind() {
184         setup();
185 
186         if (oversized) {
187         }
188         else {
189             bb.rewind();
190         }
191     }
192 
193     /** @see CachableSource 
194     */
195     public boolean isExpired() {
196         if (oversized) {
197             return true;
198         }
199         else if ((--checkIn) == 0) {
200             checkIn = CHECK_INTERVAL;
201             return file.lastModified() != stamp;
202         }
203         else {
204             return false;
205         }
206     }
207 
208     /** @see CachableSource */
209     public void setCacheCallback(Cache ch) {
210         this.cache = ch;
211     }
212 }