1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.unpack200;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22
23 import org.apache.commons.compress.harmony.pack200.BHSDCodec;
24 import org.apache.commons.compress.harmony.pack200.Codec;
25 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
26 import org.apache.commons.compress.utils.IOUtils;
27
28
29
30
31 public class SegmentHeader {
32
33 private static final byte[] EMPTY_BYTE_ARRAY = {};
34
35
36
37
38 private static final int[] magic = { 0xCA, 0xFE, 0xD0, 0x0D };
39
40 private int archiveMajor;
41
42 private int archiveMinor;
43
44 private long archiveModtime;
45
46 private long archiveSize;
47
48 private int attributeDefinitionCount;
49
50 private InputStream bandHeadersInputStream;
51
52 private int bandHeadersSize;
53
54 private int classCount;
55
56 private int cpClassCount;
57
58 private int cpDescriptorCount;
59
60 private int cpDoubleCount;
61
62 private int cpFieldCount;
63
64 private int cpFloatCount;
65
66 private int cpIMethodCount;
67
68 private int cpIntCount;
69
70 private int cpLongCount;
71
72 private int cpMethodCount;
73
74 private int cpSignatureCount;
75
76 private int cpStringCount;
77
78 private int cpUTF8Count;
79
80 private int defaultClassMajorVersion;
81
82 private int defaultClassMinorVersion;
83
84 private int innerClassCount;
85
86 private int numberOfFiles;
87
88 private int segmentsRemaining;
89
90 private SegmentOptions options;
91
92 private final Segment segment;
93
94 private int archiveSizeOffset;
95
96 public SegmentHeader(final Segment segment) {
97 this.segment = segment;
98 }
99
100
101
102
103
104
105
106
107
108
109
110 private int decodeScalar(final String name, final InputStream in, final BHSDCodec codec) throws IOException, Pack200Exception {
111 final int ret = codec.decode(in);
112 segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " as " + ret);
113 return ret;
114 }
115
116
117
118
119
120
121
122
123
124
125
126 private int[] decodeScalar(final String name, final InputStream in, final BHSDCodec codec, final int n) throws IOException, Pack200Exception {
127 segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " (" + n + ")");
128 return codec.decodeInts(n, in);
129 }
130
131 public long getArchiveModtime() {
132 return archiveModtime;
133 }
134
135 public long getArchiveSize() {
136 return archiveSize;
137 }
138
139 public int getArchiveSizeOffset() {
140 return archiveSizeOffset;
141 }
142
143 public int getAttributeDefinitionCount() {
144 return attributeDefinitionCount;
145 }
146
147
148
149
150
151
152
153
154
155
156 public InputStream getBandHeadersInputStream() {
157 if (bandHeadersInputStream == null) {
158 bandHeadersInputStream = new ByteArrayInputStream(EMPTY_BYTE_ARRAY);
159 }
160 return bandHeadersInputStream;
161
162 }
163
164 public int getBandHeadersSize() {
165 return bandHeadersSize;
166 }
167
168 public int getClassCount() {
169 return classCount;
170 }
171
172 public int getCpClassCount() {
173 return cpClassCount;
174 }
175
176 public int getCpDescriptorCount() {
177 return cpDescriptorCount;
178 }
179
180 public int getCpDoubleCount() {
181 return cpDoubleCount;
182 }
183
184 public int getCpFieldCount() {
185 return cpFieldCount;
186 }
187
188 public int getCpFloatCount() {
189 return cpFloatCount;
190 }
191
192 public int getCpIMethodCount() {
193 return cpIMethodCount;
194 }
195
196 public int getCpIntCount() {
197 return cpIntCount;
198 }
199
200 public int getCpLongCount() {
201 return cpLongCount;
202 }
203
204 public int getCpMethodCount() {
205 return cpMethodCount;
206 }
207
208 public int getCpSignatureCount() {
209 return cpSignatureCount;
210 }
211
212 public int getCpStringCount() {
213 return cpStringCount;
214 }
215
216 public int getCpUTF8Count() {
217 return cpUTF8Count;
218 }
219
220 public int getDefaultClassMajorVersion() {
221 return defaultClassMajorVersion;
222 }
223
224 public int getDefaultClassMinorVersion() {
225 return defaultClassMinorVersion;
226 }
227
228 public int getInnerClassCount() {
229 return innerClassCount;
230 }
231
232 public int getNumberOfFiles() {
233 return numberOfFiles;
234 }
235
236 public SegmentOptions getOptions() {
237 return options;
238 }
239
240 public int getSegmentsRemaining() {
241 return segmentsRemaining;
242 }
243
244 private void parseArchiveFileCounts(final InputStream in) throws IOException, Pack200Exception {
245 if (options.hasArchiveFileCounts()) {
246 setArchiveSize((long) decodeScalar("archive_size_hi", in, Codec.UNSIGNED5) << 32 | decodeScalar("archive_size_lo", in, Codec.UNSIGNED5));
247 archiveSizeOffset = in.available();
248 setSegmentsRemaining(decodeScalar("archive_next_count", in, Codec.UNSIGNED5));
249 setArchiveModtime(decodeScalar("archive_modtime", in, Codec.UNSIGNED5));
250 numberOfFiles = decodeScalar("file_count", in, Codec.UNSIGNED5);
251 }
252 }
253
254 private void parseArchiveSpecialCounts(final InputStream in) throws IOException, Pack200Exception {
255 if (getOptions().hasSpecialFormats()) {
256 bandHeadersSize = decodeScalar("band_headers_size", in, Codec.UNSIGNED5);
257 setAttributeDefinitionCount(decodeScalar("attr_definition_count", in, Codec.UNSIGNED5));
258 }
259 }
260
261 private void parseClassCounts(final InputStream in) throws IOException, Pack200Exception {
262 innerClassCount = decodeScalar("ic_count", in, Codec.UNSIGNED5);
263 defaultClassMinorVersion = decodeScalar("default_class_minver", in, Codec.UNSIGNED5);
264 defaultClassMajorVersion = decodeScalar("default_class_majver", in, Codec.UNSIGNED5);
265 classCount = decodeScalar("class_count", in, Codec.UNSIGNED5);
266 }
267
268 private void parseCpCounts(final InputStream in) throws IOException, Pack200Exception {
269 cpUTF8Count = decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5);
270 if (getOptions().hasCPNumberCounts()) {
271 cpIntCount = decodeScalar("cp_Int_count", in, Codec.UNSIGNED5);
272 cpFloatCount = decodeScalar("cp_Float_count", in, Codec.UNSIGNED5);
273 cpLongCount = decodeScalar("cp_Long_count", in, Codec.UNSIGNED5);
274 cpDoubleCount = decodeScalar("cp_Double_count", in, Codec.UNSIGNED5);
275 }
276 cpStringCount = decodeScalar("cp_String_count", in, Codec.UNSIGNED5);
277 cpClassCount = decodeScalar("cp_Class_count", in, Codec.UNSIGNED5);
278 cpSignatureCount = decodeScalar("cp_Signature_count", in, Codec.UNSIGNED5);
279 cpDescriptorCount = decodeScalar("cp_Descr_count", in, Codec.UNSIGNED5);
280 cpFieldCount = decodeScalar("cp_Field_count", in, Codec.UNSIGNED5);
281 cpMethodCount = decodeScalar("cp_Method_count", in, Codec.UNSIGNED5);
282 cpIMethodCount = decodeScalar("cp_Imethod_count", in, Codec.UNSIGNED5);
283 }
284
285 public void read(final InputStream in) throws IOException, Error, Pack200Exception {
286
287 final int[] word = decodeScalar("archive_magic_word", in, Codec.BYTE1, magic.length);
288 for (int m = 0; m < magic.length; m++) {
289 if (word[m] != magic[m]) {
290 throw new Error("Bad header");
291 }
292 }
293 setArchiveMinorVersion(decodeScalar("archive_minver", in, Codec.UNSIGNED5));
294 setArchiveMajorVersion(decodeScalar("archive_majver", in, Codec.UNSIGNED5));
295 options = new SegmentOptions(decodeScalar("archive_options", in, Codec.UNSIGNED5));
296 parseArchiveFileCounts(in);
297 parseArchiveSpecialCounts(in);
298 parseCpCounts(in);
299 parseClassCounts(in);
300
301 if (getBandHeadersSize() > 0) {
302 setBandHeadersData(IOUtils.readRange(in, getBandHeadersSize()));
303 }
304
305 archiveSizeOffset -= in.available();
306 }
307
308
309
310
311
312
313
314 private void setArchiveMajorVersion(final int version) throws Pack200Exception {
315 if (version != 150) {
316 throw new Pack200Exception("Invalid segment major version: " + version);
317 }
318 archiveMajor = version;
319 }
320
321
322
323
324
325
326
327 private void setArchiveMinorVersion(final int version) throws Pack200Exception {
328 if (version != 7) {
329 throw new Pack200Exception("Invalid segment minor version");
330 }
331 archiveMinor = version;
332 }
333
334 public void setArchiveModtime(final long archiveModtime) {
335 this.archiveModtime = archiveModtime;
336 }
337
338 public void setArchiveSize(final long archiveSize) {
339 this.archiveSize = archiveSize;
340 }
341
342 private void setAttributeDefinitionCount(final long valuie) {
343 this.attributeDefinitionCount = (int) valuie;
344 }
345
346 private void setBandHeadersData(final byte[] bandHeaders) {
347 this.bandHeadersInputStream = new ByteArrayInputStream(bandHeaders);
348 }
349
350 public void setSegmentsRemaining(final long value) {
351 segmentsRemaining = (int) value;
352 }
353
354 public void unpack() {
355
356 }
357 }