1 /*****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20 package org.apache.james.util.io;
21
22 import java.io.BufferedInputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27
28 /***
29 * @author Federico Barbieri <fede@apache.org>
30 */
31 public class ResettableFileInputStream
32 extends InputStream
33 {
34 protected static final int DEFAULT_BUFFER_SIZE = 1024;
35
36 protected final String m_filename;
37 protected int m_bufferSize;
38 protected InputStream m_inputStream;
39 protected long m_position;
40 protected long m_mark;
41 protected boolean m_isMarkSet;
42
43 public ResettableFileInputStream( final File file )
44 throws IOException
45 {
46 this( file.getCanonicalPath() );
47 }
48
49 public ResettableFileInputStream( final String filename )
50 throws IOException
51 {
52 this( filename, DEFAULT_BUFFER_SIZE );
53 }
54
55 public ResettableFileInputStream( final String filename, final int bufferSize )
56 throws IOException
57 {
58 m_bufferSize = bufferSize;
59 m_filename = filename;
60 m_position = 0;
61
62 m_inputStream = newStream();
63 }
64
65 public void mark( final int readLimit )
66 {
67 m_isMarkSet = true;
68 m_mark = m_position;
69 m_inputStream.mark( readLimit );
70 }
71
72 public boolean markSupported()
73 {
74 return true;
75 }
76
77 public void reset()
78 throws IOException
79 {
80 if( !m_isMarkSet )
81 {
82 throw new IOException( "Unmarked Stream" );
83 }
84 try
85 {
86 m_inputStream.reset();
87 }
88 catch( final IOException ioe )
89 {
90 try
91 {
92 m_inputStream.close();
93 m_inputStream = newStream();
94 m_inputStream.skip( m_mark );
95 m_position = m_mark;
96 }
97 catch( final Exception e )
98 {
99 throw new IOException( "Cannot reset current Stream: " + e.getMessage() );
100 }
101 }
102 }
103
104 protected InputStream newStream()
105 throws IOException
106 {
107 return new BufferedInputStream( new FileInputStream( m_filename ), m_bufferSize );
108 }
109
110 public int available()
111 throws IOException
112 {
113 return m_inputStream.available();
114 }
115
116 public void close() throws IOException
117 {
118 m_inputStream.close();
119 }
120
121 public int read() throws IOException
122 {
123 m_position++;
124 return m_inputStream.read();
125 }
126
127 public int read( final byte[] bytes, final int offset, final int length )
128 throws IOException
129 {
130 final int count = m_inputStream.read( bytes, offset, length );
131 m_position += count;
132 return count;
133 }
134
135 public long skip( final long count )
136 throws IOException
137 {
138 m_position += count;
139 return m_inputStream.skip( count );
140 }
141 }