First post!
[beagle.git] / Lucene.Net / Index / CompoundFileReader.cs
blobfffc832ae109da5fcd97cfb4d2a8754eabc1ed5c
1 using System;
2 using System.Collections;
3 using System.Runtime.CompilerServices;
5 using Lucene.Net.Store;
7 namespace Lucene.Net.Index
9 /* ====================================================================
10 * The Apache Software License, Version 1.1
12 * Copyright (c) 2001 The Apache Software Foundation. All rights
13 * reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
25 * distribution.
27 * 3. The end-user documentation included with the redistribution,
28 * if any, must include the following acknowledgment:
29 * "This product includes software developed by the
30 * Apache Software Foundation (http://www.apache.org/)."
31 * Alternately, this acknowledgment may appear in the software itself,
32 * if and wherever such third-party acknowledgments normally appear.
34 * 4. The names "Apache" and "Apache Software Foundation" and
35 * "Apache Lucene" must not be used to endorse or promote products
36 * derived from this software without prior written permission. For
37 * written permission, please contact apache@apache.org.
39 * 5. Products derived from this software may not be called "Apache",
40 * "Apache Lucene", nor may "Apache" appear in their name, without
41 * prior written permission of the Apache Software Foundation.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
44 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
47 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
50 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 * ====================================================================
57 * This software consists of voluntary contributions made by many
58 * individuals on behalf of the Apache Software Foundation. For more
59 * information on the Apache Software Foundation, please see
60 * <http://www.apache.org/>.
63 /// <summary>
64 /// Class for accessing a compound stream.
65 /// This class implements a directory, but is limited to only read operations.
66 /// Directory methods that would normally modify data throw an exception.
67 /// @author Dmitry Serebrennikov
68 /// @version $Id: CompoundFileReader.cs,v 1.1.1.1 2004/04/29 22:53:51 trow Exp $
69 /// </summary>
70 public class CompoundFileReader : Directory
73 private sealed class FileEntry
75 internal long offset;
76 internal long length;
79 // Base info
80 private Directory directory;
81 private String fileName;
83 // Reference count
84 //private bool open;
86 private InputStream stream;
87 private Hashtable entries = new Hashtable();
90 public CompoundFileReader(Directory dir, String name)
92 directory = dir;
93 fileName = name;
95 bool success = false;
97 try
99 stream = dir.OpenFile(name);
101 // read the directory and init files
102 int count = stream.ReadVInt();
103 FileEntry entry = null;
105 for (int i=0; i<count; i++)
107 long offset = stream.ReadLong();
108 String id = stream.ReadString();
110 if (entry != null)
112 // set length of the previous entry
113 entry.length = offset - entry.offset;
116 entry = new FileEntry();
117 entry.offset = offset;
118 entries.Add(id, entry);
121 // set the length of the final entry
122 if (entry != null)
124 entry.length = stream.Length() - entry.offset;
127 success = true;
130 finally
132 if (! success)
134 try
136 stream.Close();
138 catch (System.IO.IOException) { }
143 public Directory GetDirectory()
145 return directory;
148 public String GetName()
150 return fileName;
153 [MethodImpl(MethodImplOptions.Synchronized)]
154 public override void Close()
156 if (stream == null)
157 throw new System.IO.IOException("Already closed");
159 entries.Clear();
160 stream.Close();
161 stream = null;
164 [MethodImpl(MethodImplOptions.Synchronized)]
165 public override InputStream OpenFile(String id)
167 if (stream == null)
168 throw new System.IO.IOException("Stream closed");
170 FileEntry entry = (FileEntry) entries[id];
171 if (entry == null)
172 throw new System.IO.IOException("No sub-file with id " + id + " found");
174 return new CSInputStream(stream, entry.offset, entry.length);
177 /// <summary>
178 /// Returns an array of strings, one for each file in the directory.
179 /// </summary>
180 public override String[] List()
182 String[] res = new String[entries.Count];
183 entries.Keys.CopyTo(res, 0);
184 return res;
187 /// <summary>
188 /// Returns true iff a file with the given name exists.
189 /// </summary>
190 public override bool FileExists(String name)
192 return entries.ContainsKey(name);
195 /// <summary>
196 /// Returns the time the named file was last modified.
197 /// </summary>
198 public override long FileModified(String name)
200 return directory.FileModified(fileName);
203 /// <summary>
204 /// Set the modified time of an existing file to now.
205 /// </summary>
206 /// <param name="name"></param>
207 public override void TouchFile(String name)
209 directory.TouchFile(fileName);
212 /// <summary>
213 /// Removes an existing file in the directory.
214 /// </summary>
215 public override void DeleteFile(String name)
217 throw new InvalidOperationException();
220 /// <summary>
221 /// Renames an existing file in the directory.
222 /// If a file already exists with the new name, then it is replaced.
223 /// This replacement should be atomic. */
224 /// </summary>
225 public override void RenameFile(String from, String to)
227 throw new InvalidOperationException();
230 /// <summary>
231 /// Returns the length of a file in the directory.
232 /// </summary>
233 public override long FileLength(String name)
235 FileEntry e = (FileEntry) entries[name];
236 if (e == null)
237 throw new System.IO.IOException("File " + name + " does not exist");
238 return e.length;
241 /// <summary>
242 /// Creates a new, empty file in the directory with the given name.
243 /// </summary>
244 /// <param name="name"></param>
245 /// <returns>a stream writing the file.</returns>
246 public override OutputStream CreateFile(String name)
248 throw new InvalidOperationException();
251 /// <summary>
252 /// Construct a {@link Lock}.
253 /// </summary>
254 /// <param name="name"></param>
255 /// <returns>the name of the lock file</returns>
256 public override Lock MakeLock(String name)
258 throw new InvalidOperationException();
261 /// <summary>
262 /// Implementation of an InputStream that reads from a portion of the
263 /// compound file. The visibility is left as "package" *only* because
264 /// this helps with testing since JUnit test cases in a different class
265 /// can then access package fields of this class.
266 /// </summary>
267 public sealed class CSInputStream : InputStream
270 internal InputStream _base;
271 internal long fileOffset;
273 internal CSInputStream( InputStream _base,
274 long fileOffset,
275 long length)
277 this._base = (InputStream) _base.Clone();
278 this.fileOffset = fileOffset;
279 this.length = length; // variable in the superclass
280 SeekInternal(0); // position to the adjusted 0th byte
283 /// <summary>
284 /// Expert: implements buffer refill. Reads bytes from the current position in the input.
285 /// </summary>
286 /// <param name="b">the array to read bytes into</param>
287 /// <param name="offset">the offset in the array to start storing bytes</param>
288 /// <param name="len">the number of bytes to read</param>
289 protected override void ReadInternal(byte[] b, int offset, int len)
291 _base.ReadBytes(b, offset, len);
294 /// <summary>
295 /// Expert: implements seek. Sets current position in this file, where
296 /// the next ReadInternal(byte[],int,int) will occur.
297 /// <see>ReadInternal(byte[],int,int)</see>
298 /// </summary>
299 /// <param name="pos"></param>
300 protected override void SeekInternal(long pos)
302 if (pos > 0 && pos >= length)
303 throw new System.IO.IOException("Seek past the end of file");
305 if (pos < 0)
306 throw new System.IO.IOException("Seek to a negative offset");
308 _base.Seek(fileOffset + pos);
311 /// <summary>
312 /// Closes the stream to futher operations.
313 /// </summary>
314 public override void Close()
316 _base.Close();
319 /// <summary>
320 /// <p>Clones of a stream access the same data, and are positioned at the same
321 /// point as the stream they were cloned from.</p>p>
323 /// <p>Expert: Subclasses must ensure that clones may be positioned at
324 /// different points in the input from each other and from the stream they
325 /// were cloned from.</p>p>
326 /// </summary>
327 /// <returns>clone of this stream</returns>
328 public override Object Clone()
330 CSInputStream other = (CSInputStream) base.Clone();
331 other._base = (InputStream) _base.Clone();
332 return other;