1 /*******************************************************************************
2  * Copyright (c) 2003, 2018 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 
15 package org.eclipse.equinox.internal.cm.reliablefile;
16 
17 import java.io.*;
18 
19 //This is a copy of org.eclipse.osgi.framework.internal.reliablefile.ReliableFileInputStream
20 
21 /**
22  * A ReliableFile FileInputStream replacement class.
23  * This class can be used just like FileInputStream. The class
24  * is in partnership with ReliableFileOutputStream to avoid losing
25  * file data by using multiple files.
26  *
27  * @see			ReliableFileOutputStream
28  */
29 public class ReliableFileInputStream extends FilterInputStream {
30 	/**
31 	 * ReliableFile object for this file.
32 	 */
33 	private ReliableFile reliable;
34 
35 	/**
36 	 * size of crc and signature
37 	 */
38 	private int sigSize;
39 
40 	/**
41 	 * current position reading from file
42 	 */
43 	private int readPos;
44 
45 	/**
46 	 * total file length available for reading
47 	 */
48 	private int length;
49 
50 	/**
51 	 * Constructs a new ReliableFileInputStream on the file named <code>name</code>.  If the
52 	 * file does not exist, the <code>FileNotFoundException</code> is thrown.
53 	 * The <code>name</code> may be absolute or relative
54 	 * to the System property <code>"user.dir"</code>.
55 	 *
56 	 * @param		name	the file on which to stream reads.
57 	 * @exception 	java.io.IOException If an error occurs opening the file.
58 	 */
ReliableFileInputStream(String name)59 	public ReliableFileInputStream(String name) throws IOException {
60 		this(ReliableFile.getReliableFile(name), ReliableFile.GENERATION_LATEST, ReliableFile.OPEN_BEST_AVAILABLE);
61 	}
62 
63 	/**
64 	 * Constructs a new ReliableFileInputStream on the File <code>file</code>.  If the
65 	 * file does not exist, the <code>FileNotFoundException</code> is thrown.
66 	 *
67 	 * @param		file		the File on which to stream reads.
68 	 * @exception 	java.io.IOException If an error occurs opening the file.
69 	 */
ReliableFileInputStream(File file)70 	public ReliableFileInputStream(File file) throws IOException {
71 		this(ReliableFile.getReliableFile(file), ReliableFile.GENERATION_LATEST, ReliableFile.OPEN_BEST_AVAILABLE);
72 	}
73 
74 	/**
75 	 * Constructs a new ReliableFileInputStream on the File <code>file</code>.  If the
76 	 * file does not exist, the <code>FileNotFoundException</code> is thrown.
77 	 *
78 	 * @param file the File on which to stream reads.
79 	 * @param generation a specific generation requested.
80 	 * @param openMask mask used to open data.
81 	 * are invalid (corrupt, missing, etc).
82 	 * @exception 	java.io.IOException If an error occurs opening the file.
83 	 */
ReliableFileInputStream(File file, int generation, int openMask)84 	public ReliableFileInputStream(File file, int generation, int openMask) throws IOException {
85 		this(ReliableFile.getReliableFile(file), generation, openMask);
86 	}
87 
88 	/**
89 	 *
90 	 * @param reliable The ReliableFile on which to read.
91 	 * @param generation a specific generation requested.
92 	 * @param openMask mask used to open data.
93 	 * are invalid (corrupt, missing, etc).
94 	 * @throws IOException If an error occurs opening the file.
95 	 */
ReliableFileInputStream(ReliableFile reliable, int generation, int openMask)96 	private ReliableFileInputStream(ReliableFile reliable, int generation, int openMask) throws IOException {
97 		super(reliable.getInputStream(generation, openMask));
98 
99 		this.reliable = reliable;
100 		sigSize = reliable.getSignatureSize();
101 		readPos = 0;
102 		length = super.available();
103 		if (sigSize > length)
104 			length = 0; // shouldn't ever happen
105 		else
106 			length -= sigSize;
107 	}
108 
109 	/**
110 	 * Closes this input stream and releases any system resources associated
111 	 * with the stream.
112 	 *
113 	 * @exception 	java.io.IOException If an error occurs closing the file.
114 	 */
115 	@Override
close()116 	public synchronized void close() throws IOException {
117 		if (reliable != null) {
118 			try {
119 				super.close();
120 			} finally {
121 				reliable.closeInputFile();
122 				reliable = null;
123 			}
124 		}
125 	}
126 
127 	/**
128 	 * Override default FilterInputStream method.
129 	 * @see FilterInputStream#read(byte[], int, int)
130 	 */
131 	@Override
read(byte b[], int off, int len)132 	public synchronized int read(byte b[], int off, int len) throws IOException {
133 		if (readPos >= length) {
134 			return -1;
135 		}
136 		int num = super.read(b, off, len);
137 
138 		if (num != -1) {
139 			if (num + readPos > length) {
140 				num = length - readPos;
141 			}
142 			readPos += num;
143 		}
144 		return num;
145 	}
146 
147 	/**
148 	 * Override default FilterInputStream method.
149 	 * @see FilterInputStream#read(byte[])
150 	 */
151 	@Override
read(byte b[])152 	public synchronized int read(byte b[]) throws IOException {
153 		return read(b, 0, b.length);
154 	}
155 
156 	/**
157 	 * Override default FilterInputStream method.
158 	 * @see FilterInputStream#read()
159 	 */
160 	@Override
read()161 	public synchronized int read() throws IOException {
162 		if (readPos >= length) {
163 			return -1;
164 		}
165 		int num = super.read();
166 
167 		if (num != -1) {
168 			readPos++;
169 		}
170 		return num;
171 	}
172 
173 	/**
174 	 * Override default available method.
175 	 * @see FilterInputStream#available()
176 	 */
177 	@Override
available()178 	public synchronized int available() {
179 		if (readPos < length) // just in case
180 			return (length - readPos);
181 		return 0;
182 	}
183 
184 	/**
185 	 * Override default skip method.
186 	 * @see FilterInputStream#skip(long)
187 	 */
188 	@Override
skip(long n)189 	public synchronized long skip(long n) throws IOException {
190 		long len = super.skip(n);
191 		if (readPos + len > length)
192 			len = length - readPos;
193 		readPos += len;
194 		return len;
195 	}
196 
197 	/**
198 	 * Override default markSupported method.
199 	 * @see FilterInputStream#markSupported()
200 	 */
201 	@Override
markSupported()202 	public boolean markSupported() {
203 		return false;
204 	}
205 
206 	/**
207 	 * Override default mark method.
208 	 * @see FilterInputStream#mark(int)
209 	 */
210 	@Override
mark(int readlimit)211 	public void mark(int readlimit) {
212 		//ignore
213 	}
214 
215 	/**
216 	 * Override default reset method.
217 	 * @see FilterInputStream#reset()
218 	 */
219 	@Override
reset()220 	public void reset() throws IOException {
221 		throw new IOException("reset not supported."); //$NON-NLS-1$
222 	}
223 }
224