1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.compressors.xz;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23
24 import org.apache.commons.compress.MemoryLimitException;
25 import org.apache.commons.compress.compressors.CompressorInputStream;
26 import org.apache.commons.compress.utils.InputStreamStatistics;
27 import org.apache.commons.io.input.BoundedInputStream;
28 import org.tukaani.xz.SingleXZInputStream;
29 import org.tukaani.xz.XZ;
30 import org.tukaani.xz.XZInputStream;
31
32
33
34
35
36
37 public class XZCompressorInputStream extends CompressorInputStream implements InputStreamStatistics {
38
39
40
41
42
43
44
45
46 public static boolean matches(final byte[] signature, final int length) {
47 if (length < XZ.HEADER_MAGIC.length) {
48 return false;
49 }
50
51 for (int i = 0; i < XZ.HEADER_MAGIC.length; ++i) {
52 if (signature[i] != XZ.HEADER_MAGIC[i]) {
53 return false;
54 }
55 }
56
57 return true;
58 }
59
60 private final BoundedInputStream countingStream;
61
62 private final InputStream in;
63
64
65
66
67
68
69
70
71
72 public XZCompressorInputStream(final InputStream inputStream) throws IOException {
73 this(inputStream, false);
74 }
75
76
77
78
79
80
81
82
83
84
85
86 public XZCompressorInputStream(final InputStream inputStream, final boolean decompressConcatenated) throws IOException {
87 this(inputStream, decompressConcatenated, -1);
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public XZCompressorInputStream(final InputStream inputStream, final boolean decompressConcatenated, final int memoryLimitInKb) throws IOException {
105 countingStream = BoundedInputStream.builder().setInputStream(inputStream).get();
106 if (decompressConcatenated) {
107 in = new XZInputStream(countingStream, memoryLimitInKb);
108 } else {
109 in = new SingleXZInputStream(countingStream, memoryLimitInKb);
110 }
111 }
112
113 @Override
114 public int available() throws IOException {
115 return in.available();
116 }
117
118 @Override
119 public void close() throws IOException {
120 in.close();
121 }
122
123
124
125
126 @Override
127 public long getCompressedCount() {
128 return countingStream.getCount();
129 }
130
131 @Override
132 public int read() throws IOException {
133 try {
134 final int ret = in.read();
135 count(ret == -1 ? -1 : 1);
136 return ret;
137 } catch (final org.tukaani.xz.MemoryLimitException e) {
138 throw new MemoryLimitException(e.getMemoryNeeded(), e.getMemoryLimit(), e);
139 }
140 }
141
142 @Override
143 public int read(final byte[] buf, final int off, final int len) throws IOException {
144 if (len == 0) {
145 return 0;
146 }
147 try {
148 final int ret = in.read(buf, off, len);
149 count(ret);
150 return ret;
151 } catch (final org.tukaani.xz.MemoryLimitException e) {
152
153 throw new MemoryLimitException(e.getMemoryNeeded(), e.getMemoryLimit(), e);
154 }
155 }
156
157 @Override
158 public long skip(final long n) throws IOException {
159 try {
160 return org.apache.commons.io.IOUtils.skip(in, n);
161 } catch (final org.tukaani.xz.MemoryLimitException e) {
162
163 throw new MemoryLimitException(e.getMemoryNeeded(), e.getMemoryLimit(), e);
164 }
165 }
166 }