KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > ristretto > io > FileSourceModel


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is Ristretto Mail API.
15  *
16  * The Initial Developers of the Original Code are
17  * Timo Stich and Frederik Dietz.
18  * Portions created by the Initial Developers are Copyright (C) 2004
19  * All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */

36 package org.columba.ristretto.io;
37
38 import java.io.File JavaDoc;
39 import java.io.IOException JavaDoc;
40 import java.io.RandomAccessFile JavaDoc;
41 import java.nio.ByteBuffer JavaDoc;
42 import java.nio.channels.FileChannel JavaDoc;
43 import java.util.Timer JavaDoc;
44 import java.util.TimerTask JavaDoc;
45
46 /**
47  * FileSourceModel of a FileSource. Works together with
48  * the FileSource to efficently wrap a File
49  * in a FileSource.
50  *
51  *
52  * @author tstich
53  *
54  */

55 public class FileSourceModel {
56
57     private File JavaDoc file;
58     private FileChannel JavaDoc channel;
59     private ByteBuffer JavaDoc buffer;
60     private int bufferStart;
61     private int references;
62     
63     private CloseChannelTimerTask closeTask;
64
65     // Share one timer between all instances
66
private static Timer JavaDoc timer = new Timer JavaDoc();
67     
68     private static final int BUFFERSIZE = 61440; //byte
69
private static final long CLOSE_DELAY = 2000; //ms
70

71     
72     /**
73      * Constructs the FileSourceModel.
74      *
75      * @param file
76      * @throws IOException
77      */

78     public FileSourceModel( File JavaDoc file ) throws IOException JavaDoc {
79         this.file = file;
80         
81         buffer = ByteBuffer.allocate( BUFFERSIZE );
82
83         bufferStart = 0;
84         references = 0;
85         
86         updateBufferFromFile();
87     }
88
89     /**
90      * Get the character at the given position.
91      *
92      * @param pos
93      * @return the character at this position
94      * @throws IOException
95      */

96     public char get( int pos ) throws IOException JavaDoc {
97         // Must be read from channel or is it in the buffers
98
if( (pos < bufferStart) ) {
99             while( pos < bufferStart ) {
100                 bufferStart -= (BUFFERSIZE / 2);
101             }
102             
103             updateBufferFromFile();
104         } else
105         if (pos >= bufferStart + BUFFERSIZE ) {
106             while( pos >= bufferStart + BUFFERSIZE ) {
107                 bufferStart += (BUFFERSIZE / 2);
108             }
109             updateBufferFromFile();
110         }
111         
112         // this is a trick to avoid interpreting
113
// the byte as a signed value
114
byte value = buffer.get( pos - bufferStart );
115         int trueValue = (value & 0x080) + (value & 0x07F);
116         
117         return (char) trueValue;
118     }
119     
120     /**
121      * @throws IOException
122      */

123     private void updateBufferFromFile() throws IOException JavaDoc {
124         if( channel == null ) {
125             channel = new RandomAccessFile JavaDoc( file, "r" ).getChannel();
126         }
127
128         buffer.clear();
129         channel.read(buffer, bufferStart );
130         
131         // The channel will be closed after 2 secs
132
// idle
133
restartCloseTimer();
134     }
135
136     private void restartCloseTimer() {
137         if( closeTask != null ) closeTask.cancel();
138         closeTask = new CloseChannelTimerTask(this);
139         timer.schedule(closeTask, CLOSE_DELAY);
140     }
141
142     /**
143      * Get the lenght of the File.
144      *
145      * @return the length
146      * @throws IOException
147      */

148     public int length() throws IOException JavaDoc {
149         return (int) channel.size();
150     }
151     
152     /**
153      * Another FileSource is dependent on this
154      * model.
155      *
156      */

157     public void incReferences() {
158         references++;
159     }
160     
161     /**
162      * A dependant FileSource is closed.
163      * If none are left the FileSourceModel
164      * can be closed and the File resources
165      * can be released.
166      */

167     public void decReferences() {
168         references--;
169         if( references <= 0 ) {
170             try {
171                 close();
172             } catch (IOException JavaDoc e) {
173                 e.printStackTrace();
174             }
175         }
176     }
177     
178     /**
179      * Closes the FileSourceModel.
180      *
181      * @throws IOException
182      */

183     public void close() throws IOException JavaDoc {
184         if( channel != null) {
185             channel.close();
186             channel = null;
187         }
188     }
189
190     /**
191      * @return Returns the file.
192      */

193     public File JavaDoc getFile() {
194         return file;
195     }
196
197 }
198
199
200 class CloseChannelTimerTask extends TimerTask JavaDoc {
201     
202     FileSourceModel model;
203     
204     
205     /**
206      * Constructs the CloseChannelTimerTask
207      *
208      * @param model
209      */

210     public CloseChannelTimerTask(FileSourceModel model) {
211         super();
212         this.model = model;
213     }
214     /**
215      * @see java.lang.Runnable#run()
216      */

217     public void run() {
218         try {
219             model.close();
220         } catch (IOException JavaDoc e) {
221         }
222     }
223 }
Popular Tags