1 /*
2 * Copyright (C) 2010, Google Inc.
3 * and other copyright owners as documented in the project's IP log.
4 *
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 *
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
27 * written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44 package org.eclipse.jgit.lib;
45
46 import java.io.IOException;
47 import java.io.InputStream;
48
49 /** Stream of data coming from an object loaded by {@link ObjectLoader}. */
50 public abstract class ObjectStream extends InputStream {
51 /** @return Git object type, see {@link Constants}. */
52 public abstract int getType();
53
54 /** @return total size of object in bytes */
55 public abstract long getSize();
56
57 /**
58 * Simple stream around the cached byte array created by a loader.
59 * <p>
60 * ObjectLoader implementations can use this stream type when the object's
61 * content is small enough to be accessed as a single byte array, but the
62 * application has still requested it in stream format.
63 */
64 public static class SmallStream extends ObjectStream {
65 private final int type;
66
67 private final byte[] data;
68
69 private int ptr;
70
71 private int mark;
72
73 /**
74 * Create the stream from an existing loader's cached bytes.
75 *
76 * @param loader
77 * the loader.
78 */
79 public SmallStream(ObjectLoader loader) {
80 this(loader.getType(), loader.getCachedBytes());
81 }
82
83 /**
84 * Create the stream from an existing byte array and type.
85 *
86 *@param type
87 * the type constant for the object.
88 *@param data
89 * the fully inflated content of the object.
90 */
91 public SmallStream(int type, byte[] data) {
92 this.type = type;
93 this.data = data;
94 }
95
96 @Override
97 public int getType() {
98 return type;
99 }
100
101 @Override
102 public long getSize() {
103 return data.length;
104 }
105
106 @Override
107 public int available() {
108 return data.length - ptr;
109 }
110
111 @Override
112 public long skip(long n) {
113 int s = (int) Math.min(available(), Math.max(0, n));
114 ptr += s;
115 return s;
116 }
117
118 @Override
119 public int read() {
120 if (ptr == data.length)
121 return -1;
122 return data[ptr++] & 0xff;
123 }
124
125 @Override
126 public int read(byte[] b, int off, int len) {
127 if (ptr == data.length)
128 return -1;
129 int n = Math.min(available(), len);
130 System.arraycopy(data, ptr, b, off, n);
131 ptr += n;
132 return n;
133 }
134
135 @Override
136 public boolean markSupported() {
137 return true;
138 }
139
140 @Override
141 public void mark(int readlimit) {
142 mark = ptr;
143 }
144
145 @Override
146 public void reset() {
147 ptr = mark;
148 }
149 }
150
151 /**
152 * Simple filter stream around another stream.
153 * <p>
154 * ObjectLoader implementations can use this stream type when the object's
155 * content is available from a standard InputStream.
156 */
157 public static class Filter extends ObjectStream {
158 private final int type;
159
160 private final long size;
161
162 private final InputStream in;
163
164 /**
165 * Create a filter stream for an object.
166 *
167 * @param type
168 * the type of the object.
169 * @param size
170 * total size of the object, in bytes.
171 * @param in
172 * stream the object's raw data is available from. This
173 * stream should be buffered with some reasonable amount of
174 * buffering.
175 */
176 public Filter(int type, long size, InputStream in) {
177 this.type = type;
178 this.size = size;
179 this.in = in;
180 }
181
182 @Override
183 public int getType() {
184 return type;
185 }
186
187 @Override
188 public long getSize() {
189 return size;
190 }
191
192 @Override
193 public int available() throws IOException {
194 return in.available();
195 }
196
197 @Override
198 public long skip(long n) throws IOException {
199 return in.skip(n);
200 }
201
202 @Override
203 public int read() throws IOException {
204 return in.read();
205 }
206
207 @Override
208 public int read(byte[] b, int off, int len) throws IOException {
209 return in.read(b, off, len);
210 }
211
212 @Override
213 public boolean markSupported() {
214 return in.markSupported();
215 }
216
217 @Override
218 public void mark(int readlimit) {
219 in.mark(readlimit);
220 }
221
222 @Override
223 public void reset() throws IOException {
224 in.reset();
225 }
226
227 @Override
228 public void close() throws IOException {
229 in.close();
230 }
231 }
232 }